mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
refactor(office): remove the bundled structural checker
This commit is contained in:
1 parent
2fe9783f55
commit
fb2a554cd3
39 files changed
+123
-709
No files matched your search
@@ -528,7 +528,7 @@ it.each(['unset', 'empty', 'bundled', 'full', 'python-only', 'python-only-no-cli
|
||||
]))
|
||||
}
|
||||
if (mode === 'python-only') expect(stderr).not.toContain('ENOENT')
|
||||
if (mode === 'missing-assets') expect(stderr).toContain('check_office.py')
|
||||
if (mode === 'missing-assets') expect(stderr).toContain('SKILL.md')
|
||||
await send(3, 'shutdown')
|
||||
const exit = await child
|
||||
expect(exit.timedOut).toBe(false)
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
en: 3724c53da4f7647b
|
||||
zh: 76ae549d43c99bb4
|
||||
/deepseek-harness-desktop/key-technical-decisions/bundled-workspace-dependencies:
|
||||
en: 22f1c529983660d5
|
||||
zh: e2dad2c6b41f07ce
|
||||
en: 3368ff9b955ada69
|
||||
zh: e9209ef6ad4fd305
|
||||
/deepseek-harness-desktop/bundled-command-runtime:
|
||||
en: 372297005b57a08b
|
||||
zh: 074a635ac17e4362
|
||||
|
||||
@@ -100,7 +100,7 @@ Signed Windows packaging scans the primary runtime and application production de
|
||||
|
||||
Desktop carries independent Python, Node.js and pnpm distributions. Python includes numpy, pandas, python-docx, python-pptx, openpyxl, Pillow, lxml and XlsxWriter with their complete dependencies. The `load_workspace_dependencies` tool installs this payload offline on first use under `$DSH_HOME/dsh-runtimes/dsh-primary-runtime` (normally `~/.dsh/dsh-runtimes/dsh-primary-runtime`) and returns absolute interpreter, pnpm script and library paths plus `pythonDistributions`, the bundled distribution names and versions. The version report excludes user-installed additions. Office tasks prefer these libraries unless user or workspace instructions select another environment. Execute the pnpm script with the returned Node executable. The returned Node library directory is reserved for bundled libraries, not pnpm's global installation directory.
|
||||
|
||||
Desktop exposes the compact `office` router and named authoring/operation subskills. Authoring uses bundled Python libraries and the shared structural checker; operation skills invoke the configured Node and CLI paths. Skills live in `runtime/office-skills` outside ASAR so Python can read resources. See the [Office skill package](../../packages/skill/skill-office/README.md) for progressive loading and limitations.
|
||||
Desktop exposes the compact `office` router and named authoring/operation subskills. Authoring uses bundled Python libraries; operation skills invoke the configured Node and CLI paths. Skills live in `runtime/office-skills` outside ASAR. See the [Office skill package](../../packages/skill/skill-office/README.md) for progressive loading and limitations.
|
||||
|
||||
The payload follows the Desktop release. `runtime.json` records the Desktop version, target, top-level interpreter/package-manager versions and the Python distribution map, and a digest of the selected target’s locked payload inputs and assembly format. Distribution names use PEP 503 normalization; duplicate normalized names reject the manifest. Legacy `components` manifests remain readable through normalization, with their existing library-version consistency checks. Matching installations are reused; a dependency or archive change replaces the directory after a complete staged copy even when the Desktop version stays unchanged. Older manifests without a digest are replaced on their next installation. User-added Python packages remain only while the payload identity matches. A failed directory replacement retains the previous installation; Windows may refuse replacement while an interpreter is still running.
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ Windows 签名打包按 PE 文件内容扫描第一方运行时和应用生产
|
||||
|
||||
Desktop 携带独立的 Python、Node.js 和 pnpm 分发包。Python 包含 numpy、pandas、python-docx、python-pptx、openpyxl、Pillow、lxml、XlsxWriter 及其完整依赖。`load_workspace_dependencies` 工具首次使用时,将该产物离线安装到 `$DSH_HOME/dsh-runtimes/dsh-primary-runtime`(通常为 `~/.dsh/dsh-runtimes/dsh-primary-runtime`),并返回解释器、pnpm 脚本和库目录的绝对路径,以及记录内置分发包名称与版本的 `pythonDistributions`。版本报告不包含用户自行安装的包。Office 任务默认使用这些库,用户或工作区指令指定其他环境时遵循其要求。pnpm 脚本通过返回的 Node 可执行文件运行。返回的 Node 库目录为随包交付的库预留,不是 pnpm 的全局安装目录。
|
||||
|
||||
Desktop 展示精简的 `office` 路由及可具名调用的创作/操作子技能。创作使用内置 Python 库和共享结构检查器;操作技能调用配置的 Node 和 CLI 路径。技能位于 ASAR 外的 `runtime/office-skills`,便于 Python 读取资源。渐进加载与限制见 [Office 技能包](../../packages/skill/skill-office/README.zh.md)。
|
||||
Desktop 展示精简的 `office` 路由及可具名调用的创作/操作子技能。创作使用内置 Python 库;操作技能调用配置的 Node 和 CLI 路径。技能位于 ASAR 外的 `runtime/office-skills`。渐进加载与限制见 [Office 技能包](../../packages/skill/skill-office/README.zh.md)。
|
||||
|
||||
该产物随 Desktop 版本发布。`runtime.json` 记录 Desktop 版本、目标平台、顶层解释器和包管理器版本及 Python 分发包版本表,以及所选目标的锁定产物输入与组装格式的摘要。分发包名称按 PEP 503 归一化;名称归一化后重复时,清单会被拒绝。旧 `components` 清单通过归一化继续可读,并保留其原有库版本一致性校验。匹配的安装会被复用;依赖或压缩包变化后,即使 Desktop 版本不变,也会在完整暂存副本完成后替换目录。不含摘要的旧清单会在下次安装时被替换。用户自行添加的 Python 包仅在产物身份一致时保留。目录替换失败时保留之前的安装;解释器仍在运行时,Windows 可能拒绝替换。
|
||||
|
||||
|
||||
@@ -3062,7 +3062,7 @@ export interface Config {
|
||||
```ts config-catalog
|
||||
/** Office skill resource location. */
|
||||
export interface Config {
|
||||
/** Absolute assets directory containing skill folders and shared scripts; defaults to packaged assets. */
|
||||
/** Absolute assets directory containing skill folders; defaults to packaged assets. */
|
||||
assetRoot?: string
|
||||
/** Standalone Node executable; defaults to the current executable outside Electron and SEA. */
|
||||
node?: string
|
||||
|
||||
@@ -3064,7 +3064,7 @@ export interface Config {
|
||||
```ts config-catalog
|
||||
/** Office skill resource location. */
|
||||
export interface Config {
|
||||
/** Absolute assets directory containing skill folders and shared scripts; defaults to packaged assets. */
|
||||
/** Absolute assets directory containing skill folders; defaults to packaged assets. */
|
||||
assetRoot?: string
|
||||
/** Standalone Node executable; defaults to the current executable outside Electron and SEA. */
|
||||
node?: string
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
|
||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.2/office-checker/guide.md
|
||||
/:
|
||||
en: f4b19b20596dbad2
|
||||
zh: 25a90d5e8c51f3cd
|
||||
/office-checker-removal:
|
||||
en: fdc485db7a686d77
|
||||
zh: f2a854177c14e43d
|
||||
/office-checker-removal/change:
|
||||
en: 5639536624303537
|
||||
zh: 8d55fe469d69247c
|
||||
/office-checker-removal/migration:
|
||||
en: a76670cef92daa37
|
||||
zh: cc95cc2c84cd78d9
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
kind: upgrade-guide
|
||||
description: "Bundled Office resources no longer provide the check_office.py command."
|
||||
---
|
||||
|
||||
# Office checker removal
|
||||
|
||||
English | [中文](guide.zh.md)
|
||||
|
||||
## Change
|
||||
|
||||
Office resources no longer include `scripts/check_office.py`. Custom skills and scripts that invoke this helper must update. Authoring skills verify saved documents through their Python libraries; the provider no longer requires a shared scripts directory. Rendering, recalculation, and PDF export remain separate operations.
|
||||
|
||||
## Migration
|
||||
|
||||
1. Remove calls to `check_office.py` from custom Office workflows.
|
||||
2. Reopen saved files with python-docx, python-pptx, or openpyxl and verify the requested content, formatting, and preserved data. These checks do not provide a package-integrity report.
|
||||
3. Run the workflow and confirm that the requested edits survive reopening. Request rendering or recalculation when the task needs those operations.
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
kind: upgrade-guide
|
||||
description: "内置 Office 资源不再提供 check_office.py 命令。"
|
||||
---
|
||||
|
||||
# Office 检查器移除
|
||||
|
||||
[English](guide.md) | 中文
|
||||
|
||||
## 变更
|
||||
|
||||
Office 资源不再包含 `scripts/check_office.py`。调用该脚本的自定义技能和脚本需要更新。创作技能通过对应的 Python 库验证保存后的文档;提供者不再要求共享脚本目录。渲染、重算和 PDF 导出仍是独立操作。
|
||||
|
||||
## 迁移
|
||||
|
||||
1. 从自定义 Office 工作流中移除 `check_office.py` 调用。
|
||||
2. 用 python-docx、python-pptx 或 openpyxl 重新打开保存的文件,验证请求的内容、格式及需要保留的数据。这些检查不提供包完整性报告。
|
||||
3. 执行工作流,确认重新打开后请求的修改仍然存在。任务需要时再要求渲染或重算。
|
||||
@@ -9,23 +9,20 @@
|
||||
en: f855ac5e12b4e604
|
||||
zh: b2e875d31d56cb2e
|
||||
/deepseek-ai-dsh-skill-office/summary:
|
||||
en: 42234b5ae272eba3
|
||||
zh: 9df9a2a3ea9a9697
|
||||
en: 3f41e39809756048
|
||||
zh: 5ec8623eeb617755
|
||||
/deepseek-ai-dsh-skill-office/table-of-contents:
|
||||
en: c361195a73cf5755
|
||||
zh: 745b04e7be0be369
|
||||
/deepseek-ai-dsh-skill-office/use-this-package:
|
||||
en: 8bfffcb6f69eb597
|
||||
zh: a859a1ed72b43fde
|
||||
en: bc0460f837676d8a
|
||||
zh: be1692483d7f5daf
|
||||
/deepseek-ai-dsh-skill-office/use-this-package/progressive-loading:
|
||||
en: fd13620d7ddda0a6
|
||||
zh: 08ad6f76b0a56f47
|
||||
/deepseek-ai-dsh-skill-office/use-this-package/structural-checks:
|
||||
en: 6068327b19e24726
|
||||
zh: 75983084c98e93b6
|
||||
en: b20b58bfaab4d3f6
|
||||
zh: 084528c543b8746e
|
||||
/deepseek-ai-dsh-skill-office/understand-the-implementation:
|
||||
en: ffc20e13bda2bc49
|
||||
zh: 32d0c9572f5464f1
|
||||
en: 6946e30f3663c72f
|
||||
zh: 81dd5de9c7e61562
|
||||
/deepseek-ai-dsh-skill-office/further-exploration:
|
||||
en: 23830c100287ffb8
|
||||
zh: 7a4100e87057bc20
|
||||
@@ -36,8 +33,8 @@
|
||||
en: dc9e9205d989f1d0
|
||||
zh: 01bdbbfba743813a
|
||||
/deepseek-ai-dsh-skill-office/known-limitations-and-deferred-work:
|
||||
en: fd1f488986e15054
|
||||
zh: ac723bc3e8d48f71
|
||||
en: 1f718fc3bb4352d9
|
||||
zh: c1aa108ad2b05fdd
|
||||
/deepseek-ai-dsh-skill-office/known-limitations-and-deferred-work/dev-note:
|
||||
en: e67f633dc6fe7773
|
||||
zh: 8ec3e73528ddb1a6
|
||||
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
||||
|
||||
## Summary
|
||||
|
||||
The catalog lists the Office router and six authoring or operation skills. Full instructions load on demand. Authoring skills use the selected Python and shared checker script; operation skills supply the configured Node and LibreOffice Kit CLI paths. SDK and Desktop mount the skill provider and dependency query separately.
|
||||
The catalog lists the Office router and six authoring or operation skills. Full instructions load on demand. Authoring skills use the selected Python libraries; operation skills supply the configured Node and LibreOffice Kit CLI paths. SDK and Desktop mount the skill provider and dependency query separately.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -26,7 +26,7 @@ The catalog lists the Office router and six authoring or operation skills. Full
|
||||
<a id="use-this-package"></a>
|
||||
## Use this package
|
||||
|
||||
Mount the skill provider beside the skill registry and `dsh-tool-skill`. The provider supplies instructions and checker resources; operation skills append absolute interpreter and CLI paths when loaded.
|
||||
Mount the skill provider beside the skill registry and `dsh-tool-skill`. The provider supplies skill instructions; operation skills append absolute interpreter and CLI paths when loaded.
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-skill-office'
|
||||
@@ -35,7 +35,7 @@ Mount the skill provider beside the skill registry and `dsh-tool-skill`. The pro
|
||||
|
||||
| Field | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `assetRoot` | Carrier resources or packaged `assets/` | Absolute directory containing the seven skill folders and shared `scripts/`. |
|
||||
| `assetRoot` | Carrier resources or packaged `assets/` | Absolute directory containing the seven skill folders. |
|
||||
| `node` | Host Node.js | Standalone Node executable for operation skills; packaged carriers supply it explicitly. |
|
||||
| `cli` | Installed Kit CLI | Absolute CLI entry; `false` disables operation execution. |
|
||||
|
||||
@@ -77,12 +77,6 @@ flowchart TD
|
||||
|
||||
New files and content, data, or formula edits do not require rendering solely because they include incidental basic formatting. Preview images use a private, randomly named temporary directory inside the workspace and are removed after inspection. Loaded instructions remain in session history after an operation finishes. The diagram describes ordinary presets across supported clients; it does not change the shell-only definition of minimal or sdk-minimal.
|
||||
|
||||
### Structural checks
|
||||
|
||||
`"<python>" "<skill-directory>/../scripts/check_office.py" <file> --out <report.json>` reads DOCX, PPTX, and XLSX without changing the source. The shared Python checker validates ZIP/XML and internal relationships, summarizes document structure, and optionally checks required text or slide/sheet counts. It requires only the Python standard library. Invalid files and report-write failures return a JSON failure report. Structural success does not establish appearance, feature preservation, or calculated formula values.
|
||||
|
||||
Word content edits inspect the requested content and formatting, and finish after targeted verification and the shared structural check pass. Package-level investigation requires a concrete failure, ambiguity, unsupported feature, or explicit user requirement.
|
||||
|
||||
-----
|
||||
|
||||
<a id="understand-the-implementation"></a>
|
||||
@@ -99,7 +93,7 @@ The provider registers no tools or activation projection. Loaded skill results r
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | Resource registration and unchanged skill bodies. |
|
||||
|
||||
| [`assets/`](assets/) | Router, six subskills, and read-only OOXML checker. |
|
||||
| [`assets/`](assets/) | Router and six subskills. |
|
||||
|
||||
</details>
|
||||
|
||||
@@ -127,8 +121,8 @@ Skill results append to history without changing tool declarations, and loaded t
|
||||
|
||||
<a id="known-limitations-and-deferred-work"></a>
|
||||
|
||||
- The provider does not install authoring libraries. The checker needs Python 3.9 or later.
|
||||
- LibreOffice output can differ from native Office applications; structural checks cannot certify appearance.
|
||||
- The provider does not install authoring libraries.
|
||||
- LibreOffice output can differ from native Office applications.
|
||||
- Legacy, encrypted, and macro-enabled files need an appropriate separate workflow.
|
||||
|
||||
<a id="dev-note"></a>
|
||||
|
||||
@@ -9,7 +9,7 @@ kind: "package-reference"
|
||||
|
||||
## 概述
|
||||
|
||||
目录列出 Office 路由及六个创作或操作技能,完整说明按需加载。创作技能使用选定的 Python 和共享检查脚本;操作技能提供配置的 Node 与 LibreOffice Kit CLI 路径。SDK 和 Desktop 分别挂载技能提供者和依赖查询。
|
||||
目录列出 Office 路由及六个创作或操作技能,完整说明按需加载。创作技能使用选定的 Python 库;操作技能提供配置的 Node 与 LibreOffice Kit CLI 路径。SDK 和 Desktop 分别挂载技能提供者和依赖查询。
|
||||
|
||||
## 目录
|
||||
|
||||
@@ -26,7 +26,7 @@ kind: "package-reference"
|
||||
<a id="use-this-package"></a>
|
||||
## 使用本包
|
||||
|
||||
在技能注册表和 `dsh-tool-skill` 旁挂载技能提供者。提供者负责说明和检查器资源;操作技能在加载时附加解释器和 CLI 的绝对路径。
|
||||
在技能注册表和 `dsh-tool-skill` 旁挂载技能提供者。提供者负责技能说明;操作技能在加载时附加解释器和 CLI 的绝对路径。
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-skill-office'
|
||||
@@ -35,7 +35,7 @@ kind: "package-reference"
|
||||
|
||||
| 字段 | 默认值 | 含义 |
|
||||
|---|---|---|
|
||||
| `assetRoot` | 载体资源或包内 `assets/` | 包含七个技能目录及共享 `scripts/` 的绝对路径。 |
|
||||
| `assetRoot` | 载体资源或包内 `assets/` | 包含七个技能目录的绝对路径。 |
|
||||
| `node` | 宿主 Node.js | 操作技能使用的独立 Node 可执行程序;打包载体显式提供。 |
|
||||
| `cli` | 已安装 Kit CLI | CLI 入口的绝对路径;`false` 禁用操作执行。 |
|
||||
|
||||
@@ -77,12 +77,6 @@ flowchart TD
|
||||
|
||||
新建文件以及内容、数据或公式修改,不会仅因附带基础格式调整而需要渲染。预览图片保存在工作区内随机命名的私有临时目录中,并在检查后删除。操作结束后,已加载的说明仍属于会话历史。图中描述各端常规预设,不改变 minimal 或 sdk-minimal 的纯 shell 定义。
|
||||
|
||||
### 结构检查
|
||||
|
||||
`"<python>" "<skill-directory>/../scripts/check_office.py" <file> --out <report.json>` 读取 DOCX、PPTX 和 XLSX,不修改源文件。共享 Python 检查器验证 ZIP/XML 和内部关系、汇总文档结构,并可检查必需文本或幻灯片/工作表数量。它仅依赖 Python 标准库。无效文件和报告写入失败会返回 JSON 失败报告。结构检查成功不代表外观、功能保留或公式计算值通过验证。
|
||||
|
||||
Word 内容修改只检查请求的内容和格式,目标验证与共享结构检查通过后即可结束。包级调查仅用于具体失败、歧义、不支持的特性或明确的用户要求。
|
||||
|
||||
-----
|
||||
|
||||
<a id="understand-the-implementation"></a>
|
||||
@@ -99,7 +93,7 @@ Word 内容修改只检查请求的内容和格式,目标验证与共享结构
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | 注册资源并返回原始技能正文。 |
|
||||
|
||||
| [`assets/`](assets/) | 路由、六个子技能与只读 OOXML 检查器。 |
|
||||
| [`assets/`](assets/) | 路由与六个子技能。 |
|
||||
|
||||
</details>
|
||||
|
||||
@@ -127,8 +121,8 @@ Word 内容修改只检查请求的内容和格式,目标验证与共享结构
|
||||
|
||||
<a id="known-limitations-and-deferred-work"></a>
|
||||
|
||||
- 提供者不安装创作库。检查器需要 Python 3.9 或更新版本。
|
||||
- LibreOffice 输出可能不同于原生 Office 应用;结构检查无法认证外观。
|
||||
- 提供者不安装创作库。
|
||||
- LibreOffice 输出可能不同于原生 Office 应用。
|
||||
- 旧格式、加密和启用宏的文件需要适用的独立工作流。
|
||||
|
||||
<a id="dev-note"></a>
|
||||
|
||||
@@ -21,15 +21,7 @@ python-docx does not paginate or render documents. Do not represent ordinary rep
|
||||
|
||||
## Check and deliver
|
||||
|
||||
Use the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.
|
||||
|
||||
```text
|
||||
"<python>" "<skill-directory>/../scripts/check_office.py" <document.docx> --out <checks.json>
|
||||
```
|
||||
|
||||
It checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.
|
||||
|
||||
For routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.
|
||||
Reopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.
|
||||
|
||||
Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.
|
||||
|
||||
|
||||
@@ -55,18 +55,8 @@ Check that text and images fit the slide dimensions, titles form a useful sequen
|
||||
|
||||
## Check and deliver
|
||||
|
||||
Run the shared structural checker when `office-check` is available:
|
||||
Reopen the saved presentation with python-pptx to verify the requested slide count, content, formatting, chart data, and notes, including unchanged content that must be preserved. These checks do not establish text fit, readable contrast, or rendering fidelity.
|
||||
|
||||
In PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.
|
||||
|
||||
```text
|
||||
"<python>" "<skill-directory>/../scripts/check_office.py" <presentation.pptx> --out <checks.json>
|
||||
```
|
||||
|
||||
It checks ZIP/XML integrity and internal relationships and reports slide count and extracted text. Use repeated `--contains TEXT` arguments for required slide text and `--count N` for a requested slide count; `--contains` excludes chart text and speaker notes. Reopen the file to check the requested edits, chart data, and notes. Structural success does not establish text fit, alignment, readable contrast, or rendering fidelity.
|
||||
|
||||
If the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.
|
||||
|
||||
Deliver after the requested content and structural checks pass. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changes unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.
|
||||
Deliver after the requested edits are verified. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changes unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.
|
||||
|
||||
Call `present({"files":[{"path":"report-edited.pptx"}]})` with the actual final PPTX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and leave intermediate images and reports out of delivery unless requested. If `present` is unavailable, use the session's supported file delivery method.
|
||||
@@ -41,22 +41,10 @@ Do not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx
|
||||
|
||||
## Check and deliver
|
||||
|
||||
Run the shared structural checker when `office-check` is available:
|
||||
|
||||
Run the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.
|
||||
|
||||
In PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.
|
||||
|
||||
```text
|
||||
"<python>" "<skill-directory>/../scripts/check_office.py" <workbook.xlsx> --out <checks.json>
|
||||
```
|
||||
|
||||
It checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.
|
||||
|
||||
If the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.
|
||||
Reopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.
|
||||
|
||||
Load `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.
|
||||
|
||||
Load `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after structural and data checks pass and the required operations finish.
|
||||
Load `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.
|
||||
|
||||
Call `present({"files":[{"path":"report.xlsx"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.
|
||||
@@ -1,279 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Read-only OOXML checks and structural summaries; no rendering or formula evaluation.
|
||||
|
||||
Run with INPUT.docx, INPUT.pptx, or INPUT.xlsx. Optional --contains assertions
|
||||
check extracted text; DOCX excludes comments, glossary text, and unreferenced parts or notes.
|
||||
--count checks slides or sheets. JSON escapes non-ASCII
|
||||
characters and goes to stdout and optionally --out. Exit 0 means the requested
|
||||
structural checks passed, 1 means a document, assertion, or report write failed, and 2 means
|
||||
invalid command-line arguments.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import posixpath
|
||||
import sys
|
||||
import zipfile
|
||||
import zlib
|
||||
from pathlib import Path
|
||||
from urllib.parse import unquote, urlsplit
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
W_NAMESPACES = (
|
||||
"http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
||||
"http://purl.oclc.org/ooxml/wordprocessingml/main",
|
||||
)
|
||||
A_NAMESPACES = (
|
||||
"http://schemas.openxmlformats.org/drawingml/2006/main",
|
||||
"http://purl.oclc.org/ooxml/drawingml/main",
|
||||
)
|
||||
P_NAMESPACES = (
|
||||
"http://schemas.openxmlformats.org/presentationml/2006/main",
|
||||
"http://purl.oclc.org/ooxml/presentationml/main",
|
||||
)
|
||||
S_NAMESPACES = (
|
||||
"http://schemas.openxmlformats.org/spreadsheetml/2006/main",
|
||||
"http://purl.oclc.org/ooxml/spreadsheetml/main",
|
||||
)
|
||||
R_NAMESPACES = (
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
||||
"http://purl.oclc.org/ooxml/officeDocument/relationships",
|
||||
)
|
||||
MAIN_PARTS = {
|
||||
".docx": ("word/document.xml", "wordprocessingml.document.main+xml"),
|
||||
".pptx": ("ppt/presentation.xml", "presentationml.presentation.main+xml"),
|
||||
".xlsx": ("xl/workbook.xml", "spreadsheetml.sheet.main+xml"),
|
||||
}
|
||||
|
||||
|
||||
def namespace(root: ET.Element, supported: tuple[str, ...], part: str) -> str:
|
||||
"""Return the main XML namespace after checking its OOXML variant."""
|
||||
uri = root.tag[1:].split("}", 1)[0] if root.tag.startswith("{") else ""
|
||||
if uri not in supported:
|
||||
raise ValueError(f"{part} uses unsupported XML namespace: {uri or '(none)'}")
|
||||
return "{" + uri + "}"
|
||||
|
||||
|
||||
def relationship_id(node: ET.Element, part: str) -> str:
|
||||
"""Read an office-document relationship id from Transitional or Strict OOXML."""
|
||||
for uri in R_NAMESPACES:
|
||||
value = node.get("{" + uri + "}id")
|
||||
if value is not None:
|
||||
return value
|
||||
raise ValueError(f"{part} has a reference without a relationship id")
|
||||
|
||||
|
||||
def relationship_types(kind: str) -> set[str]:
|
||||
"""Return the Transitional and Strict relationship type names for one role."""
|
||||
return {f"{uri}/{kind}" for uri in R_NAMESPACES}
|
||||
|
||||
|
||||
def iter_namespaces(root: ET.Element, namespaces: tuple[str, ...], local_name: str):
|
||||
"""Iterate matching elements across Transitional and Strict namespaces."""
|
||||
for uri in namespaces:
|
||||
yield from root.iter("{" + uri + "}" + local_name)
|
||||
|
||||
|
||||
def relationship_target(part: str, target: str) -> str:
|
||||
"""Resolve a package relationship without fetching external resources."""
|
||||
path = unquote(urlsplit(target).path)
|
||||
return posixpath.normpath(path.lstrip("/") if path.startswith("/") else posixpath.join(posixpath.dirname(part), path))
|
||||
|
||||
|
||||
def relationships(part: str, xml: dict[str, ET.Element], types: set[str] | None = None) -> dict[str, str]:
|
||||
path = posixpath.join(posixpath.dirname(part), "_rels", posixpath.basename(part) + ".rels")
|
||||
root = xml.get(path)
|
||||
if root is None:
|
||||
return {}
|
||||
return {
|
||||
rel.attrib["Id"]: relationship_target(part, rel.attrib["Target"])
|
||||
for rel in root if rel.get("TargetMode") != "External" and (types is None or rel.get("Type") in types)
|
||||
}
|
||||
|
||||
|
||||
def related_xml(part: str, reference: str, links: dict[str, str], xml: dict[str, ET.Element]) -> ET.Element:
|
||||
"""Read a related XML part with diagnostics naming its source and reference."""
|
||||
if reference not in links:
|
||||
raise ValueError(f"{part} references missing relationship: {reference}")
|
||||
target = links[reference]
|
||||
if target not in xml:
|
||||
raise ValueError(f"{part} relationship {reference} targets a non-XML member: {target}")
|
||||
return xml[target]
|
||||
|
||||
|
||||
def inspect_docx(xml: dict[str, ET.Element]) -> tuple[dict, str]:
|
||||
part = "word/document.xml"
|
||||
root = xml[part]
|
||||
w = namespace(root, W_NAMESPACES, part)
|
||||
body = root.find(f"{w}body")
|
||||
if body is None:
|
||||
raise ValueError("word/document.xml has no document body")
|
||||
tables = []
|
||||
for table in body.iter(f"{w}tbl"):
|
||||
grid = table.findall(f"{w}tblGrid/{w}gridCol")
|
||||
rows = table.findall(f"{w}tr")
|
||||
# Merged cells span logical grid columns; counting physical cells loses them.
|
||||
columns = len(grid) if grid else max((sum(
|
||||
int(cell.find(f"{w}tcPr/{w}gridSpan").get(f"{w}val", "1"))
|
||||
if cell.find(f"{w}tcPr/{w}gridSpan") is not None else 1
|
||||
for cell in row.findall(f"{w}tc")
|
||||
) for row in rows), default=0)
|
||||
tables.append({"rows": len(rows), "columns": columns})
|
||||
sections = []
|
||||
for section in body.iter(f"{w}sectPr"):
|
||||
size = section.find(f"{w}pgSz")
|
||||
margins = section.find(f"{w}pgMar")
|
||||
sections.append({
|
||||
"page_twips": {} if size is None else {key.removeprefix(w): value for key, value in size.attrib.items()},
|
||||
"margins_twips": {} if margins is None else {key.removeprefix(w): value for key, value in margins.attrib.items()},
|
||||
})
|
||||
text_parts = [body]
|
||||
for kind in ("header", "footer"):
|
||||
links = relationships(part, xml, relationship_types(kind))
|
||||
for section in body.iter(f"{w}sectPr"):
|
||||
for reference in section.findall(f"{w}{kind}Reference"):
|
||||
text_parts.append(related_xml(part, relationship_id(reference, part), links, xml))
|
||||
for kind in ("footnote", "endnote"):
|
||||
references = {node.attrib[f"{w}id"] for node in body.iter(f"{w}{kind}Reference")}
|
||||
if not references:
|
||||
continue
|
||||
links = relationships(part, xml, relationship_types(f"{kind}s"))
|
||||
for reference in links:
|
||||
tree = related_xml(part, reference, links, xml)
|
||||
text_parts.extend(note for note in tree.findall(f"{w}{kind}") if note.get(f"{w}id") in references)
|
||||
text = "\n".join("".join(node.text or "" for node in paragraph.iter(f"{w}t")) for tree in text_parts
|
||||
for paragraph in tree.iter(f"{w}p"))
|
||||
return {"paragraphs": len(list(body.iter(f"{w}p"))), "tables": tables, "sections": sections}, text
|
||||
|
||||
|
||||
def inspect_pptx(xml: dict[str, ET.Element]) -> tuple[dict, str]:
|
||||
part = "ppt/presentation.xml"
|
||||
links = relationships(part, xml)
|
||||
root = xml[part]
|
||||
p = namespace(root, P_NAMESPACES, part)
|
||||
slides = root.findall(f"{p}sldIdLst/{p}sldId")
|
||||
texts = []
|
||||
for slide in slides:
|
||||
reference = relationship_id(slide, part)
|
||||
tree = related_xml(part, reference, links, xml)
|
||||
texts.append("\n".join("".join(node.text or "" for node in iter_namespaces(paragraph, A_NAMESPACES, "t"))
|
||||
for paragraph in iter_namespaces(tree, A_NAMESPACES, "p")))
|
||||
return {"slides": len(slides)}, "\n".join(texts)
|
||||
|
||||
|
||||
def inspect_xlsx(xml: dict[str, ET.Element]) -> tuple[dict, str]:
|
||||
part = "xl/workbook.xml"
|
||||
links = relationships(part, xml)
|
||||
root = xml[part]
|
||||
s = namespace(root, S_NAMESPACES, part)
|
||||
sheets = []
|
||||
texts = []
|
||||
shared = xml.get("xl/sharedStrings.xml")
|
||||
shared_s = s if shared is None else namespace(shared, S_NAMESPACES, "xl/sharedStrings.xml")
|
||||
shared_strings = [] if shared is None else [
|
||||
"".join(node.text or "" for node in item.iter(f"{shared_s}t")) for item in shared.iter(f"{shared_s}si")
|
||||
]
|
||||
for sheet in root.findall(f"{s}sheets/{s}sheet"):
|
||||
reference = relationship_id(sheet, part)
|
||||
tree = related_xml(part, reference, links, xml)
|
||||
sheet_s = namespace(tree, S_NAMESPACES, links[reference])
|
||||
cells = list(tree.iter(f"{sheet_s}c"))
|
||||
formulas = sum(cell.find(f"{sheet_s}f") is not None for cell in cells)
|
||||
sheets.append({"name": sheet.attrib["name"], "cells": len(cells), "formulas": formulas})
|
||||
for cell in cells:
|
||||
if cell.get("t") == "s":
|
||||
value = cell.findtext(f"{sheet_s}v", "")
|
||||
location = f"{links[reference]} cell {cell.get('r', '(no reference)')}"
|
||||
try:
|
||||
index = int(value)
|
||||
except ValueError as error:
|
||||
raise ValueError(f"{location}: invalid shared string index {value!r}") from error
|
||||
if not 0 <= index < len(shared_strings):
|
||||
raise ValueError(f"{location}: shared string index out of range: {index}")
|
||||
texts.append(shared_strings[index])
|
||||
texts.extend("".join(node.text or "" for node in cell.iter(f"{sheet_s}t")) for cell in cells)
|
||||
texts.extend(cell.findtext(f"{sheet_s}v", "") for cell in cells if cell.get("t") == "str")
|
||||
texts.append(sheet.attrib["name"])
|
||||
return {"sheets": sheets, "formulas_evaluated": False}, "\n".join(texts)
|
||||
|
||||
|
||||
def inspect(path: Path) -> tuple[dict, str]:
|
||||
"""Validate package members and relationships before inspecting the main part."""
|
||||
main, content_type = MAIN_PARTS[path.suffix.lower()]
|
||||
with zipfile.ZipFile(path) as archive:
|
||||
members = archive.namelist()
|
||||
if len(members) != len(set(members)):
|
||||
raise ValueError("ZIP contains duplicate member names")
|
||||
corrupt = archive.testzip()
|
||||
if corrupt is not None:
|
||||
raise ValueError(f"ZIP member failed its CRC check: {corrupt}")
|
||||
xml = {name: ET.fromstring(archive.read(name)) for name in members
|
||||
if name.endswith((".xml", ".rels"))}
|
||||
if main not in xml:
|
||||
raise ValueError(f"missing main part: {main}")
|
||||
types = xml.get("[Content_Types].xml")
|
||||
if types is None or not any(node.get("PartName") == "/" + main
|
||||
and node.get("ContentType", "").endswith(content_type) for node in types):
|
||||
raise ValueError(f"[Content_Types].xml does not declare {main} as {path.suffix.lower()}")
|
||||
for name, tree in xml.items():
|
||||
if not name.endswith(".rels"):
|
||||
continue
|
||||
source = "" if name == "_rels/.rels" else posixpath.join(posixpath.dirname(posixpath.dirname(name)), posixpath.basename(name)[:-5])
|
||||
for rel in tree:
|
||||
if rel.get("TargetMode") == "External":
|
||||
continue
|
||||
target = relationship_target(source, rel.attrib["Target"])
|
||||
if target not in members:
|
||||
raise ValueError(f"{name} references missing package member: {target}")
|
||||
if path.suffix.lower() == ".docx":
|
||||
return inspect_docx(xml)
|
||||
if path.suffix.lower() == ".pptx":
|
||||
return inspect_pptx(xml)
|
||||
return inspect_xlsx(xml)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("input", type=Path)
|
||||
parser.add_argument("--out", type=Path)
|
||||
parser.add_argument("--contains", action="append", default=[], metavar="TEXT")
|
||||
parser.add_argument("--count", type=int, help="expected slide or sheet count")
|
||||
args = parser.parse_args()
|
||||
if args.input.suffix.lower() not in MAIN_PARTS:
|
||||
parser.error("input must be .docx, .pptx, or .xlsx; converting the filename does not convert its contents")
|
||||
if args.count is not None and (args.count < 0 or args.input.suffix.lower() == ".docx"):
|
||||
parser.error("--count must be non-negative and applies only to slides or sheets")
|
||||
if args.out is not None and args.out.resolve() == args.input.resolve():
|
||||
parser.error("--out must differ from the input document")
|
||||
checks = []
|
||||
summary = {}
|
||||
try:
|
||||
summary, text = inspect(args.input)
|
||||
checks.append({"id": "package", "status": "pass"})
|
||||
for required in args.contains:
|
||||
checks.append({"id": "contains", "status": "pass" if required in text else "fail", "text": required})
|
||||
if args.count is not None:
|
||||
actual = summary.get("slides", len(summary.get("sheets", [])))
|
||||
checks.append({"id": "count", "status": "pass" if actual == args.count else "fail", "expected": args.count, "actual": actual})
|
||||
except (OSError, ValueError, KeyError, RuntimeError, ET.ParseError, zipfile.BadZipFile, zlib.error) as error:
|
||||
checks.append({"id": "package", "status": "fail", "detail": str(error)})
|
||||
failed = any(check["status"] == "fail" for check in checks)
|
||||
report = {"format": args.input.suffix.lower()[1:], "verdict": "fail" if failed else "pass", "checks": checks, "summary": summary}
|
||||
output = json.dumps(report, ensure_ascii=True, indent=2) + "\n"
|
||||
if args.out is not None:
|
||||
try:
|
||||
args.out.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.out.write_text(output, encoding="utf-8")
|
||||
except OSError as error:
|
||||
failed = True
|
||||
report["verdict"] = "fail"
|
||||
checks.append({"id": "output", "status": "fail", "detail": str(error)})
|
||||
output = json.dumps(report, ensure_ascii=True, indent=2) + "\n"
|
||||
sys.stdout.write(output)
|
||||
return 1 if failed else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Bundled Office workflows and filesystem resources for document authoring and checks. */
|
||||
/** Bundled Office workflows and filesystem resources for document authoring and operations. */
|
||||
|
||||
import { readFileSync, statSync } from 'node:fs'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
@@ -14,7 +14,7 @@ const SKILL_NAMES = ['office', 'office-docx', 'office-pptx', 'office-xlsx', 'off
|
||||
|
||||
/** Office skill resource location. */
|
||||
export interface Config {
|
||||
/** Absolute assets directory containing skill folders and shared scripts; defaults to packaged assets. */
|
||||
/** Absolute assets directory containing skill folders; defaults to packaged assets. */
|
||||
assetRoot?: string
|
||||
/** Standalone Node executable; defaults to the current executable outside Electron and SEA. */
|
||||
node?: string
|
||||
@@ -69,9 +69,6 @@ function officeRuntime(config: Config): string {
|
||||
export function apply(ctx: Context, config: Config = {}): void {
|
||||
const assetRoot = config.assetRoot ?? fileURLToPath(new URL('../assets/', import.meta.url))
|
||||
if (!isAbsolute(assetRoot)) throw new Error('skill-office: assetRoot must be an absolute directory')
|
||||
if (!statSync(join(assetRoot, 'scripts', 'check_office.py')).isFile()) {
|
||||
throw new Error('skill-office: assets must contain scripts/check_office.py')
|
||||
}
|
||||
const candidates: SkillCandidate[] = SKILL_NAMES.map((skillName) => {
|
||||
const directory = join(assetRoot, skillName)
|
||||
const path = join(directory, 'SKILL.md')
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
"""Exercise the distributed checker without requiring external Office libraries."""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
CHECKER = Path(__file__).resolve().parents[1] / "assets/scripts/check_office.py"
|
||||
W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||
P = "http://schemas.openxmlformats.org/presentationml/2006/main"
|
||||
A = "http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
S = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
STRICT_W = "http://purl.oclc.org/ooxml/wordprocessingml/main"
|
||||
STRICT_P = "http://purl.oclc.org/ooxml/presentationml/main"
|
||||
STRICT_A = "http://purl.oclc.org/ooxml/drawingml/main"
|
||||
STRICT_S = "http://purl.oclc.org/ooxml/spreadsheetml/main"
|
||||
STRICT_R = "http://purl.oclc.org/ooxml/officeDocument/relationships"
|
||||
PKG = "http://schemas.openxmlformats.org/package/2006/relationships"
|
||||
|
||||
|
||||
class OfficeCheckTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.directory = tempfile.TemporaryDirectory(prefix="dsh-office-check-")
|
||||
self.addCleanup(self.directory.cleanup)
|
||||
self.root = Path(self.directory.name)
|
||||
|
||||
def package(self, suffix, parts, compression=zipfile.ZIP_STORED):
|
||||
primary, mime = {
|
||||
"docx": ("word/document.xml", "wordprocessingml.document.main+xml"),
|
||||
"pptx": ("ppt/presentation.xml", "presentationml.presentation.main+xml"),
|
||||
"xlsx": ("xl/workbook.xml", "spreadsheetml.sheet.main+xml"),
|
||||
}[suffix]
|
||||
path = self.root / ("中文 document." + suffix)
|
||||
with zipfile.ZipFile(path, "w", compression=compression) as archive:
|
||||
archive.writestr("[Content_Types].xml", '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
|
||||
f'<Override PartName="/{primary}" ContentType="application/vnd.openxmlformats-officedocument.{mime}"/></Types>')
|
||||
for name, content in parts.items():
|
||||
archive.writestr(name, content)
|
||||
return path
|
||||
|
||||
def run_check(self, path, *args):
|
||||
before = path.read_bytes()
|
||||
output = self.root / "checks.json"
|
||||
result = subprocess.run([sys.executable, str(CHECKER), str(path), "--out", str(output), *args],
|
||||
capture_output=True, text=True, timeout=10)
|
||||
self.assertEqual(path.read_bytes(), before)
|
||||
self.assertEqual(result.stderr, "", result.stderr)
|
||||
report = json.loads(result.stdout)
|
||||
self.assertEqual(report, json.loads(output.read_text(encoding="utf-8")))
|
||||
return result.returncode, report
|
||||
|
||||
def test_docx_merged_cells_distinct_sections_and_cjk_are_not_layout_failures(self):
|
||||
path = self.package("docx", {"word/document.xml": f'''<w:document xmlns:w="{W}"><w:body>
|
||||
<w:p><w:r><w:t>中文报告</w:t></w:r><w:pPr><w:sectPr><w:pgSz w:w="16000"/><w:pgMar w:left="1000" w:right="1000"/></w:sectPr></w:pPr></w:p>
|
||||
<w:tbl><w:tblGrid><w:gridCol w:w="5000"/><w:gridCol w:w="5000"/></w:tblGrid><w:tr><w:tc><w:tcPr><w:gridSpan w:val="2"/></w:tcPr><w:p><w:r><w:t>合并标题</w:t></w:r></w:p></w:tc></w:tr></w:tbl>
|
||||
<w:sectPr><w:pgSz w:w="6000"/><w:pgMar w:left="1000" w:right="1000"/></w:sectPr>
|
||||
</w:body></w:document>'''})
|
||||
code, report = self.run_check(path, "--contains", "中文报告")
|
||||
self.assertEqual(code, 0)
|
||||
self.assertEqual(report["summary"]["tables"], [{"rows": 1, "columns": 2}])
|
||||
self.assertEqual(len(report["summary"]["sections"]), 2)
|
||||
code, report = self.run_check(path, "--contains", "Missing requested title")
|
||||
self.assertEqual(code, 1)
|
||||
self.assertEqual(report["checks"][-1]["status"], "fail")
|
||||
|
||||
def test_pptx_checks_slide_count_and_relationships(self):
|
||||
parts = {
|
||||
"ppt/presentation.xml": f'<p:presentation xmlns:p="{P}" xmlns:r="{R}"><p:sldIdLst><p:sldId id="256" r:id="r1"/></p:sldIdLst></p:presentation>',
|
||||
"ppt/_rels/presentation.xml.rels": f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="slides/slide1.xml"/></Relationships>',
|
||||
"ppt/slides/slide1.xml": f'<p:sld xmlns:p="{P}" xmlns:a="{A}"><a:p><a:r><a:t>季度总结</a:t></a:r></a:p></p:sld>',
|
||||
}
|
||||
path = self.package("pptx", parts)
|
||||
self.assertEqual(self.run_check(path, "--contains", "季度总结", "--count", "1")[0], 0)
|
||||
self.assertEqual(self.run_check(path, "--count", "2")[0], 1)
|
||||
parts["ppt/_rels/presentation.xml.rels"] = f'<Relationships xmlns="{PKG}"/>'
|
||||
code, report = self.run_check(self.package("pptx", parts))
|
||||
self.assertEqual(code, 1)
|
||||
self.assertIn("ppt/presentation.xml", report["checks"][0]["detail"])
|
||||
self.assertIn("r1", report["checks"][0]["detail"])
|
||||
parts["ppt/_rels/presentation.xml.rels"] = f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="slides/slide1.xml"/></Relationships>'
|
||||
del parts["ppt/slides/slide1.xml"]
|
||||
path = self.package("pptx", parts)
|
||||
code, report = self.run_check(path)
|
||||
self.assertEqual(code, 1)
|
||||
self.assertIn("missing package member", report["checks"][0]["detail"])
|
||||
|
||||
def test_docx_content_follows_section_and_note_references(self):
|
||||
parts = {
|
||||
"word/document.xml": f'''<w:document xmlns:w="{W}" xmlns:r="{R}"><w:body>
|
||||
<w:p><w:r><w:t>Main text</w:t><w:footnoteReference w:id="2"/><w:endnoteReference w:id="3"/></w:r></w:p>
|
||||
<w:sectPr><w:headerReference w:type="default" r:id="header"/><w:footerReference w:type="default" r:id="footer"/></w:sectPr>
|
||||
</w:body></w:document>''',
|
||||
"word/_rels/document.xml.rels": f'''<Relationships xmlns="{PKG}">
|
||||
<Relationship Id="header" Type="{R}/header" Target="custom/header.xml"/>
|
||||
<Relationship Id="footer" Type="{R}/footer" Target="custom/footer.xml"/>
|
||||
<Relationship Id="unused-header" Type="{R}/header" Target="custom/unused-header.xml"/>
|
||||
<Relationship Id="unused-footer" Type="{R}/footer" Target="custom/unused-footer.xml"/>
|
||||
<Relationship Id="notes" Type="{R}/footnotes" Target="custom/notes.xml"/>
|
||||
<Relationship Id="endnotes" Type="{R}/endnotes" Target="custom/endnotes.xml"/>
|
||||
<Relationship Id="comments" Type="{R}/comments" Target="comments.xml"/>
|
||||
<Relationship Id="glossary" Type="{R}/glossaryDocument" Target="glossary/document.xml"/>
|
||||
</Relationships>''',
|
||||
"word/custom/header.xml": f'<w:hdr xmlns:w="{W}"><w:p><w:r><w:t>Linked header</w:t></w:r></w:p></w:hdr>',
|
||||
"word/custom/footer.xml": f'<w:ftr xmlns:w="{W}"><w:p><w:r><w:t>Linked footer</w:t></w:r></w:p></w:ftr>',
|
||||
"word/custom/unused-header.xml": f'<w:hdr xmlns:w="{W}"><w:p><w:r><w:t>Retained header only</w:t></w:r></w:p></w:hdr>',
|
||||
"word/custom/unused-footer.xml": f'<w:ftr xmlns:w="{W}"><w:p><w:r><w:t>Retained footer only</w:t></w:r></w:p></w:ftr>',
|
||||
"word/custom/notes.xml": f'''<w:footnotes xmlns:w="{W}">
|
||||
<w:footnote w:id="2"><w:p><w:r><w:t>Linked note</w:t></w:r></w:p></w:footnote>
|
||||
<w:footnote w:id="4"><w:p><w:r><w:t>Unused note only</w:t></w:r></w:p></w:footnote>
|
||||
</w:footnotes>''',
|
||||
"word/custom/endnotes.xml": f'''<w:endnotes xmlns:w="{W}">
|
||||
<w:endnote w:id="3"><w:p><w:r><w:t>Linked endnote</w:t></w:r></w:p></w:endnote>
|
||||
<w:endnote w:id="5"><w:p><w:r><w:t>Unused endnote only</w:t></w:r></w:p></w:endnote>
|
||||
</w:endnotes>''',
|
||||
"word/comments.xml": f'<w:comments xmlns:w="{W}"><w:comment><w:p><w:r><w:t>Comment only</w:t></w:r></w:p></w:comment></w:comments>',
|
||||
"word/glossary/document.xml": f'<w:glossaryDocument xmlns:w="{W}"><w:p><w:r><w:t>Building block only</w:t></w:r></w:p></w:glossaryDocument>',
|
||||
"word/header9.xml": f'<w:hdr xmlns:w="{W}"><w:p><w:r><w:t>Unused header only</w:t></w:r></w:p></w:hdr>',
|
||||
}
|
||||
path = self.package("docx", parts)
|
||||
self.assertEqual(self.run_check(path, "--contains", "Main text", "--contains", "Linked header", "--contains", "Linked footer",
|
||||
"--contains", "Linked note", "--contains", "Linked endnote")[0], 0)
|
||||
for text in ["Comment only", "Building block only", "Unused header only", "Retained header only", "Retained footer only",
|
||||
"Unused note only", "Unused endnote only"]:
|
||||
with self.subTest(text=text):
|
||||
code, report = self.run_check(path, "--contains", text)
|
||||
self.assertEqual(code, 1)
|
||||
self.assertEqual(report["checks"][-1]["status"], "fail")
|
||||
|
||||
def test_relationships_to_non_xml_members_report_source_reference_and_target(self):
|
||||
for suffix, main, references in [
|
||||
("pptx", "ppt/presentation.xml", f'<p:presentation xmlns:p="{P}" xmlns:r="{R}"><p:sldIdLst><p:sldId id="256" r:id="r1"/></p:sldIdLst></p:presentation>'),
|
||||
("xlsx", "xl/workbook.xml", f'<workbook xmlns="{S}" xmlns:r="{R}"><sheets><sheet name="Data" sheetId="1" r:id="r1"/></sheets></workbook>'),
|
||||
]:
|
||||
with self.subTest(format=suffix):
|
||||
folder, filename = main.split("/")
|
||||
target = f"{folder}/media/image1.png"
|
||||
path = self.package(suffix, {
|
||||
main: references,
|
||||
f"{folder}/_rels/{filename}.rels": f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="media/image1.png"/></Relationships>',
|
||||
target: b"image bytes",
|
||||
})
|
||||
code, report = self.run_check(path)
|
||||
self.assertEqual(code, 1)
|
||||
detail = report["checks"][0]["detail"]
|
||||
for expected in [main, "r1", target]:
|
||||
self.assertIn(expected, detail)
|
||||
|
||||
def test_xlsx_counts_formulas_without_claiming_recalculation(self):
|
||||
path = self.package("xlsx", {
|
||||
"xl/workbook.xml": f'<workbook xmlns="{S}" xmlns:r="{R}"><sheets><sheet name="Data" sheetId="1" r:id="r1"/></sheets></workbook>',
|
||||
"xl/_rels/workbook.xml.rels": f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="/xl/worksheets/sheet1.xml"/></Relationships>',
|
||||
"xl/worksheets/sheet1.xml": f'<worksheet xmlns="{S}"><sheetData><row r="1"><c r="A1" t="inlineStr"><is><t>收入</t></is></c><c r="B1"><v>4</v></c><c r="C1"><f>B1*2</f><v/></c></row></sheetData></worksheet>',
|
||||
})
|
||||
code, report = self.run_check(path, "--contains", "收入", "--count", "1")
|
||||
self.assertEqual(code, 0)
|
||||
self.assertEqual(report["summary"], {"sheets": [{"name": "Data", "cells": 3, "formulas": 1}], "formulas_evaluated": False})
|
||||
|
||||
def test_strict_ooxml_namespaces_are_inspected(self):
|
||||
docx = self.package("docx", {
|
||||
"word/document.xml": f'<w:document xmlns:w="{STRICT_W}"><w:body><w:p><w:r><w:t>Strict Word</w:t></w:r></w:p></w:body></w:document>',
|
||||
})
|
||||
self.assertEqual(self.run_check(docx, "--contains", "Strict Word")[0], 0)
|
||||
|
||||
pptx = self.package("pptx", {
|
||||
"ppt/presentation.xml": f'<p:presentation xmlns:p="{STRICT_P}" xmlns:r="{STRICT_R}"><p:sldIdLst><p:sldId id="256" r:id="r1"/></p:sldIdLst></p:presentation>',
|
||||
"ppt/_rels/presentation.xml.rels": f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="slides/slide1.xml"/></Relationships>',
|
||||
"ppt/slides/slide1.xml": f'<p:sld xmlns:p="{STRICT_P}" xmlns:a="{STRICT_A}"><a:p><a:r><a:t>Strict Slides</a:t></a:r></a:p></p:sld>',
|
||||
})
|
||||
self.assertEqual(self.run_check(pptx, "--contains", "Strict Slides", "--count", "1")[0], 0)
|
||||
|
||||
xlsx = self.package("xlsx", {
|
||||
"xl/workbook.xml": f'''<workbook xmlns="{STRICT_S}" xmlns:r="{STRICT_R}"><sheets>
|
||||
<sheet name="First" sheetId="1" r:id="r1"/><sheet name="Second" sheetId="2" r:id="r2"/>
|
||||
</sheets></workbook>''',
|
||||
"xl/_rels/workbook.xml.rels": f'''<Relationships xmlns="{PKG}">
|
||||
<Relationship Id="r1" Target="worksheets/sheet1.xml"/><Relationship Id="r2" Target="worksheets/sheet2.xml"/>
|
||||
</Relationships>''',
|
||||
"xl/worksheets/sheet1.xml": f'<worksheet xmlns="{STRICT_S}"><sheetData><row r="1"><c r="A1" t="inlineStr"><is><t>Strict Sheet</t></is></c></row></sheetData></worksheet>',
|
||||
"xl/worksheets/sheet2.xml": f'<worksheet xmlns="{STRICT_S}"><sheetData/></worksheet>',
|
||||
})
|
||||
code, report = self.run_check(xlsx, "--contains", "Strict Sheet", "--count", "2")
|
||||
self.assertEqual(code, 0)
|
||||
self.assertEqual([sheet["name"] for sheet in report["summary"]["sheets"]], ["First", "Second"])
|
||||
|
||||
def test_xlsx_checks_only_cell_referenced_shared_strings(self):
|
||||
parts = {
|
||||
"xl/workbook.xml": f'<workbook xmlns="{S}" xmlns:r="{R}"><sheets><sheet name="Data" sheetId="1" r:id="r1"/></sheets></workbook>',
|
||||
"xl/_rels/workbook.xml.rels": f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="/xl/worksheets/sheet1.xml"/></Relationships>',
|
||||
"xl/sharedStrings.xml": f'<sst xmlns="{S}"><si><t>Deleted value</t></si><si><r><t>实际</t></r><r><t>内容</t></r></si></sst>',
|
||||
"xl/worksheets/sheet1.xml": f'<worksheet xmlns="{S}"><sheetData><row r="1"><c r="A1" t="s"><v>1</v></c><c r="B1" t="inlineStr"><is><t>Inline value</t></is></c></row></sheetData></worksheet>',
|
||||
}
|
||||
path = self.package("xlsx", parts)
|
||||
self.assertEqual(self.run_check(path, "--contains", "实际内容", "--contains", "Inline value")[0], 0)
|
||||
code, report = self.run_check(path, "--contains", "Deleted value")
|
||||
self.assertEqual(code, 1)
|
||||
self.assertEqual(report["checks"][-1]["status"], "fail")
|
||||
for index in ["-1", "2", "invalid", ""]:
|
||||
with self.subTest(index=index):
|
||||
parts["xl/worksheets/sheet1.xml"] = f'<worksheet xmlns="{S}"><sheetData><row r="1"><c r="A1" t="s"><v>{index}</v></c></row></sheetData></worksheet>'
|
||||
code, report = self.run_check(self.package("xlsx", parts))
|
||||
self.assertEqual(code, 1)
|
||||
self.assertEqual(report["checks"][0]["status"], "fail")
|
||||
self.assertIn("xl/worksheets/sheet1.xml", report["checks"][0]["detail"])
|
||||
self.assertIn("A1", report["checks"][0]["detail"])
|
||||
parts["xl/_rels/workbook.xml.rels"] = f'<Relationships xmlns="{PKG}"/>'
|
||||
code, report = self.run_check(self.package("xlsx", parts))
|
||||
self.assertEqual(code, 1)
|
||||
self.assertIn("xl/workbook.xml", report["checks"][0]["detail"])
|
||||
self.assertIn("r1", report["checks"][0]["detail"])
|
||||
|
||||
def test_xlsx_empty_or_missing_string_values_remain_json_reports(self):
|
||||
for cell_type, expected in [("s", 1), ("str", 0)]:
|
||||
for value in ["<v/>", ""]:
|
||||
with self.subTest(cell_type=cell_type, value=value):
|
||||
path = self.package("xlsx", {
|
||||
"xl/workbook.xml": f'<workbook xmlns="{S}" xmlns:r="{R}"><sheets><sheet name="Data" sheetId="1" r:id="r1"/></sheets></workbook>',
|
||||
"xl/_rels/workbook.xml.rels": f'<Relationships xmlns="{PKG}"><Relationship Id="r1" Target="worksheets/sheet1.xml"/></Relationships>',
|
||||
"xl/worksheets/sheet1.xml": f'<worksheet xmlns="{S}"><sheetData><row r="1"><c r="A1" t="{cell_type}">{value}</c></row></sheetData></worksheet>',
|
||||
})
|
||||
code, report = self.run_check(path)
|
||||
self.assertEqual(code, expected)
|
||||
self.assertEqual(report["verdict"], "fail" if expected else "pass")
|
||||
if cell_type == "s":
|
||||
self.assertIn("A1: invalid shared string index ''", report["checks"][0]["detail"])
|
||||
|
||||
def test_output_directory_failure_is_json_and_preserves_the_document(self):
|
||||
path = self.package("docx", {"word/document.xml": f'<w:document xmlns:w="{W}"><w:body/></w:document>'})
|
||||
before = path.read_bytes()
|
||||
result = subprocess.run([sys.executable, str(CHECKER), str(path), "--out", str(self.root)], capture_output=True, text=True, timeout=10)
|
||||
self.assertEqual(result.returncode, 1)
|
||||
self.assertEqual(result.stderr, "")
|
||||
report = json.loads(result.stdout)
|
||||
self.assertEqual(report["verdict"], "fail")
|
||||
self.assertEqual(report["checks"][-1]["id"], "output")
|
||||
self.assertEqual(path.read_bytes(), before)
|
||||
|
||||
def test_encrypted_package_returns_json_failure(self):
|
||||
path = Path(__file__).parent / "fixtures/encrypted.xlsx"
|
||||
code, report = self.run_check(path)
|
||||
self.assertEqual(code, 1)
|
||||
self.assertIn("encrypted", report["checks"][0]["detail"])
|
||||
|
||||
def test_corrupt_deflate_member_returns_json_package_failure(self):
|
||||
path = self.package("docx", {
|
||||
"word/document.xml": f'<w:document xmlns:w="{W}"><w:body/></w:document>',
|
||||
}, compression=zipfile.ZIP_DEFLATED)
|
||||
with zipfile.ZipFile(path) as archive:
|
||||
member = archive.getinfo("word/document.xml")
|
||||
data = bytearray(path.read_bytes())
|
||||
name_length = int.from_bytes(data[member.header_offset + 26:member.header_offset + 28], "little")
|
||||
extra_length = int.from_bytes(data[member.header_offset + 28:member.header_offset + 30], "little")
|
||||
compressed = member.header_offset + 30 + name_length + extra_length
|
||||
data[compressed] = 0x07 # BTYPE=3 is reserved and invalid in a DEFLATE block.
|
||||
path.write_bytes(data)
|
||||
code, report = self.run_check(path)
|
||||
self.assertEqual(code, 1)
|
||||
self.assertEqual(report["checks"][0]["id"], "package")
|
||||
self.assertEqual(report["checks"][0]["status"], "fail")
|
||||
self.assertTrue(report["checks"][0]["detail"])
|
||||
|
||||
def test_invalid_zip_and_xml_fail_and_output_cannot_overwrite_input(self):
|
||||
path = self.root / "broken.docx"
|
||||
path.write_bytes(b"not an Office archive")
|
||||
self.assertEqual(self.run_check(path)[0], 1)
|
||||
path = self.package("docx", {"word/document.xml": "<broken>"})
|
||||
self.assertEqual(self.run_check(path)[0], 1)
|
||||
before = path.read_bytes()
|
||||
result = subprocess.run([sys.executable, str(CHECKER), str(path), "--out", str(path)], capture_output=True, timeout=10)
|
||||
self.assertEqual(result.returncode, 2)
|
||||
self.assertEqual(path.read_bytes(), before)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,14 +0,0 @@
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { expect, it } from 'vitest'
|
||||
|
||||
it.each(['utf-8', 'cp1252'])('executes the shipped OOXML checker against valid, edited, and broken documents with %s stdout', (encoding) => {
|
||||
const python = process.env.DSH_OFFICE_TEST_PYTHON ?? (process.platform === 'win32' ? 'python' : 'python3')
|
||||
const result = spawnSync(python, [fileURLToPath(new URL('./check_office_test.py', import.meta.url))], {
|
||||
env: { ...process.env, PYTHONIOENCODING: encoding },
|
||||
encoding: 'utf8', timeout: 30_000,
|
||||
})
|
||||
expect(result.error).toBeUndefined()
|
||||
expect(result.signal, result.stderr + result.stdout).toBeNull()
|
||||
expect(result.status, result.stderr + result.stdout).toBe(0)
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Real Word content edits finish with targeted verification and the shared checker. */
|
||||
/** Real Word content edits preserve formatting without package-wide investigation. */
|
||||
import { readFile, readdir, writeFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
@@ -60,11 +60,7 @@ assert Document('input.docx').paragraphs[0].text == 'Quarterly revenue'
|
||||
if (event.type === 'tool/ptc-dispatch') return [{ name: event.data.name, arguments: JSON.stringify(event.data.arguments) }]
|
||||
return []
|
||||
})
|
||||
const commands = calls.filter(call => call.name === 'bash' || call.name === 'pwsh')
|
||||
.map(call => (JSON.parse(call.arguments) as { command: string }).command)
|
||||
const programs = JSON.stringify(calls)
|
||||
const checks = commands.filter(command => command.includes('check_office.py') && command.includes('--out'))
|
||||
expect(checks).toHaveLength(1)
|
||||
expect(programs).not.toMatch(/\b(?:inspect|docx|zipfile)\.py\b/u)
|
||||
expect(programs).not.toMatch(
|
||||
/\bunzip\b|\bextractall\s*\(|\bnamelist\s*\(|\bcore_properties\b|docProps\/|word\/(?:document|styles)\.xml/u,
|
||||
|
||||
@@ -136,11 +136,8 @@ describe('bundled Office skills', () => {
|
||||
await ctx.plugin(SkillRegistry)
|
||||
expect(() => { SkillOffice.apply(ctx, { assetRoot: 'assets' }) }).toThrow('absolute directory')
|
||||
await cp(assets, root, { recursive: true })
|
||||
await rm(join(root, 'scripts', 'check_office.py'))
|
||||
await cp(join(assets, 'office-docx'), join(root, 'scripts', 'check_office.py'), { recursive: true })
|
||||
expect(() => { SkillOffice.apply(ctx, { assetRoot: root }) }).toThrow('scripts/check_office.py')
|
||||
await rm(join(root, 'scripts', 'check_office.py'), { recursive: true })
|
||||
await cp(join(assets, 'scripts', 'check_office.py'), join(root, 'scripts', 'check_office.py'))
|
||||
await rm(join(root, 'office-docx', 'SKILL.md'))
|
||||
expect(() => { SkillOffice.apply(ctx, { assetRoot: root }) }).toThrow('SKILL.md')
|
||||
await writeFile(join(root, 'office-docx', 'SKILL.md'), '# Missing frontmatter\ndescription: body text\n')
|
||||
expect(() => { SkillOffice.apply(ctx, { assetRoot: root }) }).toThrow('has no YAML frontmatter')
|
||||
for (const header of ['', 'null', 'scalar', 'name: office-docx', 'description: 3', 'description: ""']) {
|
||||
|
||||
@@ -186,7 +186,6 @@ else:
|
||||
? answer.data.message.content.flatMap(block => block.type === 'text' ? [block.text] : []).join('\n').slice(0, 800) : undefined })
|
||||
expect(loaded, diagnostic).toContain('office-xlsx')
|
||||
expect(calls.some(call => call.name === 'load_workspace_dependencies'), diagnostic).toBe(true)
|
||||
expect(commands, diagnostic).toContain('check_office.py')
|
||||
if (kind === 'formula') {
|
||||
expect(loaded, diagnostic).toContain('office-recalculate')
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
en: 1ea1d8e6d2c14b02
|
||||
zh: 8e0b9903158667a1
|
||||
/deepseek-harness-runtime-bin/installed-commands-and-artifacts:
|
||||
en: 7b8deffca5ba029f
|
||||
zh: 96f59e4c785720f4
|
||||
en: c880421134bfc93e
|
||||
zh: cf998878378405a8
|
||||
/deepseek-harness-runtime-bin/python-module-api:
|
||||
en: 78a200e328d96637
|
||||
zh: f3b7a0b69b7a39e0
|
||||
|
||||
@@ -25,7 +25,7 @@ primary_runtime = download_primary_runtime()
|
||||
|
||||
`DSH_RESOURCE_CACHE` selects an absolute cache root, defaulting to `~/.cache/deepseek-harness/resources`. Resource identities include the release's locked inputs. Downloads verify archive hashes and package identities, preserve executable permissions, and publish completed directories atomically. Failed downloads can be retried. `DSH_RESOURCE_DOWNLOAD_TIMEOUT_MS` bounds each archive download, including its body; the default is `300000`, and accepted values are integers from `1` to `2147483647`. Downloads follow the Harness proxy environment policy. Installed wheel files are never modified. Release versions have separate cache directories; unused versions require manual removal. Downloads use the locked upstream URLs without a registry or mirror override.
|
||||
|
||||
On subsequent launches the packaged bootstrap exposes downloaded resources to the SDK profile. `DSH_PRIMARY_RUNTIME` overrides the cached authoring environment; an empty value disables its query. `DSH_OFFICE_SIDECAR` can select an absolute sidecar directory with its standalone Node. The Office checker is included in the wheel; users may provide their own Python environment and document libraries without downloading the authoring environment. Office skills are available when either resource is selected; authoring-only deployments expose the skills with the Kit CLI disabled. External authoring payloads retain the `primary-runtime/` plus sibling `office-skills/` layout. The SDK reads resources in place without copying them into `DSH_HOME`. The `sdk-minimal` profile does not mount these providers.
|
||||
On subsequent launches the packaged bootstrap exposes downloaded resources to the SDK profile. `DSH_PRIMARY_RUNTIME` overrides the cached authoring environment; an empty value disables its query. `DSH_OFFICE_SIDECAR` can select an absolute sidecar directory with its standalone Node. Users may provide their own Python environment and document libraries without downloading the authoring environment. Office skills are available when either resource is selected; authoring-only deployments expose the skills with the Kit CLI disabled. External authoring payloads retain the `primary-runtime/` plus sibling `office-skills/` layout. The SDK reads resources in place without copying them into `DSH_HOME`. The `sdk-minimal` profile does not mount these providers.
|
||||
|
||||
Skill selection is independent of delivery: project, custom-directory, and user filesystem skills override same-name bundled skills. An SDK patch can disable only the Office provider while retaining the Python query:
|
||||
|
||||
@@ -34,7 +34,7 @@ Skill selection is independent of delivery: project, custom-directory, and user
|
||||
disabled: true
|
||||
```
|
||||
|
||||
Office skills call `dsoffice` and `office-check` through the profile's shell commands. See the [Office provider](../../packages/skill/skill-office/README.md#use-this-package) for command selection and replacing the skill collection and shared checker. Configuration patches apply at process startup; changing skills does not require rebuilding the runtime wheel or Python environment.
|
||||
Office operation skills invoke the configured Node and Kit CLI through the profile's shell commands. See the [Office provider](../../packages/skill/skill-office/README.md#use-this-package) for command selection and replacing the skill collection. Configuration patches apply at process startup; changing skills does not require rebuilding the runtime wheel or Python environment.
|
||||
|
||||
Repository builds also materialize a dev-only `runtime/node/` carrier. It runs `node runtime/node/runtime-bootstrap.mjs` on system Node 22.19 or newer. It is never selected automatically and is excluded from wheels and sdists.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ primary_runtime = download_primary_runtime()
|
||||
|
||||
`DSH_RESOURCE_CACHE` 指定绝对缓存根目录,默认为 `~/.cache/deepseek-harness/resources`。资源身份包含发布版本锁定的输入。下载会校验归档哈希和包身份、保留执行权限,并原子发布完整目录。下载失败后可重试。`DSH_RESOURCE_DOWNLOAD_TIMEOUT_MS` 限制每个归档的下载耗时,包含响应内容;默认值为 `300000`,接受 `1` 到 `2147483647` 的整数。下载遵循 Harness 代理环境策略。已安装的 wheel 文件不会被修改。不同发布版本使用独立缓存目录;不再使用的版本需手动删除。下载使用锁定的上游 URL,不提供 registry 或镜像覆盖。
|
||||
|
||||
后续启动时,打包 bootstrap 将已下载资源提供给 SDK profile。`DSH_PRIMARY_RUNTIME` 覆盖缓存中的创作环境;空值禁用其查询。`DSH_OFFICE_SIDECAR` 可选择包含独立 Node 的绝对 sidecar 目录。Office checker 随 wheel 提供;用户可自行提供 Python 环境和文档库,无需下载创作环境。选择任一种资源即可使用 Office skills;仅有创作环境时,skills 中的 Kit CLI 被禁用。外部创作载荷保留 `primary-runtime/` 及同级 `office-skills/` 布局。SDK 原位读取资源,不复制到 `DSH_HOME`。`sdk-minimal` profile 不挂载这些提供方。
|
||||
后续启动时,打包 bootstrap 将已下载资源提供给 SDK profile。`DSH_PRIMARY_RUNTIME` 覆盖缓存中的创作环境;空值禁用其查询。`DSH_OFFICE_SIDECAR` 可选择包含独立 Node 的绝对 sidecar 目录。用户可自行提供 Python 环境和文档库,无需下载创作环境。选择任一种资源即可使用 Office skills;仅有创作环境时,skills 中的 Kit CLI 被禁用。外部创作载荷保留 `primary-runtime/` 及同级 `office-skills/` 布局。SDK 原位读取资源,不复制到 `DSH_HOME`。`sdk-minimal` profile 不挂载这些提供方。
|
||||
|
||||
选择 skills 与交付资源相互独立:项目、自定义目录和用户文件系统 skills 优先于同名随包 skills。SDK patch 可以仅禁用 Office 提供方,同时保留 Python 查询:
|
||||
|
||||
@@ -34,7 +34,7 @@ primary_runtime = download_primary_runtime()
|
||||
disabled: true
|
||||
```
|
||||
|
||||
Office 技能通过 profile 的 shell 命令调用 `dsoffice` 与 `office-check`。命令选择及替换技能集合、共用检查脚本的方式见 [Office 提供方](../../packages/skill/skill-office/README.zh.md#use-this-package)。配置 patch 在进程启动时生效;切换技能无需重建 runtime wheel 或 Python 环境。
|
||||
Office 操作技能通过 profile 的 shell 命令调用配置的 Node 和 Kit CLI。命令选择及替换技能集合的方式见 [Office 提供方](../../packages/skill/skill-office/README.zh.md#use-this-package)。配置 patch 在进程启动时生效;切换技能无需重建 runtime wheel 或 Python 环境。
|
||||
|
||||
仓库构建还会物化仅限开发的 `runtime/node/` 载体。它在系统 Node 22.19 或更高版本上运行 `node runtime/node/runtime-bootstrap.mjs`。系统不会自动选择它,而且 wheel 包与 sdist 均不包含它。
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ def validate_resources(root: Path | zipfile.Path, target: str) -> None:
|
||||
executable = python_root / ("python.exe" if platform == "win32" else "bin/python3")
|
||||
packages = python_root / ("Lib/site-packages" if platform == "win32" else f"lib/python{version.rsplit('.', 1)[0]}/site-packages")
|
||||
node = root / "primary-runtime/dependencies/node/bin" / ("node.exe" if platform == "win32" else "node")
|
||||
required = [executable, node, root / "office-skills/scripts/check_office.py"]
|
||||
required = [executable, node]
|
||||
required.extend(root / f"office-skills/office-{kind}/SKILL.md" for kind in ("docx", "pptx", "xlsx"))
|
||||
for path in required:
|
||||
if not path.is_file():
|
||||
@@ -57,7 +57,7 @@ def validate_downloads(root: Path | zipfile.Path, target: str) -> dict:
|
||||
or not isinstance(value.get("office"), list) or not value["office"]
|
||||
or not isinstance(value.get("pnpm"), dict)):
|
||||
raise ValueError(f"invalid runtime download manifest: {path}")
|
||||
for file in ["scripts/check_office.py", *(f"office-{kind}/SKILL.md" for kind in ("docx", "pptx", "xlsx"))]:
|
||||
for file in (f"office-{kind}/SKILL.md" for kind in ("docx", "pptx", "xlsx")):
|
||||
if not (root / "office-skills" / file).is_file():
|
||||
raise FileNotFoundError(f"runtime Office skill is missing: {root / 'office-skills' / file}")
|
||||
return value
|
||||
|
||||
@@ -150,9 +150,9 @@ def test_stage_runtime_copies_platform_payload(
|
||||
office_asset.parent.mkdir(parents=True)
|
||||
office_asset.write_bytes(b"office data")
|
||||
resources = executable.with_name(executable.name.removeprefix("deepseek-harness-sdk-runtime-").removesuffix(".exe"))
|
||||
resource = resources / "office-skills/scripts/check_office.py"
|
||||
resource = resources / "office-skills/office-docx/SKILL.md"
|
||||
resource.parent.mkdir(parents=True)
|
||||
resource.write_text("checker")
|
||||
resource.write_text("# Word documents\n")
|
||||
destination = tmp_path / "staging"
|
||||
|
||||
build_python_release.stage_runtime(destination, "1.2.3", executable, executable.name)
|
||||
@@ -164,7 +164,7 @@ def test_stage_runtime_copies_platform_payload(
|
||||
if path.is_file()
|
||||
} == expected
|
||||
assert not (runtime_dir / office.name).exists()
|
||||
assert (runtime_dir / resources.name / resource.relative_to(resources)).read_text() == "checker"
|
||||
assert (runtime_dir / resources.name / resource.relative_to(resources)).read_text() == "# Word documents\n"
|
||||
pyproject = (destination / "pyproject.toml").read_text()
|
||||
assert 'license = "MIT"' in pyproject
|
||||
assert 'license-files = ["LICENSE", "THIRD_PARTY_NOTICES.md"]' in pyproject
|
||||
|
||||
@@ -56,7 +56,7 @@ def _resource_sidecars(executable: Path, native_targets: tuple[str, ...] = ("dar
|
||||
node.chmod(0o755)
|
||||
packages = python.parent if tag.startswith("win-") else python.parent.parent
|
||||
(packages / ("Lib/site-packages" if tag.startswith("win-") else "lib/python3.12/site-packages")).mkdir(parents=True)
|
||||
for file in ["scripts/check_office.py", *(f"office-{kind}/SKILL.md" for kind in ("docx", "pptx", "xlsx"))]:
|
||||
for file in (f"office-{kind}/SKILL.md" for kind in ("docx", "pptx", "xlsx")):
|
||||
path = resources / "office-skills" / file
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.touch()
|
||||
@@ -372,7 +372,7 @@ def test_download_decodes_utf8_in_an_ascii_locale(tmp_path: Path) -> None:
|
||||
|
||||
|
||||
@pytest.mark.parametrize("missing", ["primary-runtime/runtime.json", "primary-runtime/dependencies/python/bin/python3",
|
||||
"primary-runtime/dependencies/node/bin/node", "office-skills/scripts/check_office.py"])
|
||||
"primary-runtime/dependencies/node/bin/node", "office-skills/office-docx/SKILL.md"])
|
||||
def test_primary_download_rejects_an_incomplete_payload(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, missing: str) -> None:
|
||||
_resource_sidecars(tmp_path / "deepseek-harness-sdk-runtime-linux-x64")
|
||||
root = tmp_path / "linux-x64"
|
||||
@@ -420,7 +420,7 @@ def test_download_manifest_rejects_invalid_wheel_resources(tmp_path: Path, inval
|
||||
path = root / "downloads.json"
|
||||
manifest = json.loads(path.read_text(encoding="utf-8"))
|
||||
if invalid == "skills":
|
||||
(root / "office-skills/scripts/check_office.py").unlink()
|
||||
(root / "office-skills/office-docx/SKILL.md").unlink()
|
||||
with pytest.raises(FileNotFoundError, match="Office skill"):
|
||||
validate_downloads(root, "linux-x64")
|
||||
else:
|
||||
|
||||
@@ -137,8 +137,7 @@ it('copies complete Office resources outside the application archive and removes
|
||||
try {
|
||||
const source = join(root, 'package', 'assets')
|
||||
const destination = join(root, 'Contents', 'Resources', 'runtime', 'office-skills')
|
||||
await mkdir(join(source, 'scripts'), { recursive: true })
|
||||
await writeFile(join(source, 'scripts', 'check_office.py'), 'print("checker")\n')
|
||||
await mkdir(source, { recursive: true })
|
||||
for (const name of ['office-docx', 'office-pptx', 'office-xlsx']) {
|
||||
await mkdir(join(source, name))
|
||||
await writeFile(join(source, name, 'SKILL.md'), `# ${name}\n`)
|
||||
@@ -149,7 +148,6 @@ it('copies complete Office resources outside the application archive and removes
|
||||
for (const name of ['office-docx', 'office-pptx', 'office-xlsx']) {
|
||||
expect(await readFile(join(destination, name, 'SKILL.md'), 'utf8')).toBe(`# ${name}\n`)
|
||||
}
|
||||
expect(await readFile(join(destination, 'scripts', 'check_office.py'), 'utf8')).toBe('print("checker")\n')
|
||||
await expect(readFile(join(destination, 'obsolete.py'))).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
} finally { await rm(root, { recursive: true, force: true }) }
|
||||
})
|
||||
|
||||
@@ -262,7 +262,7 @@ export function smokePrimaryRuntime(root: string, environment: NodeJS.ProcessEnv
|
||||
const options = { stdio: 'inherit', timeout: 120_000, env: environment } as const
|
||||
execFileSync(entries.python, ['-I', '-B', '-c', 'import decimal, xml.parsers.expat, lzma, uuid, numpy, pandas; assert numpy.arange(4).sum() == 6; assert pandas.DataFrame({"n": [1, 2]}).n.sum() == 3'], options)
|
||||
execFileSync(entries.python, ['-I', '-B', join(import.meta.dirname, 'smoke.py'), JSON.stringify(manifest.pythonPackages),
|
||||
manifest.python, join(dirname(root), 'office-skills', 'scripts', 'check_office.py')], options)
|
||||
manifest.python], options)
|
||||
execFileSync(entries.python, ['-I', '-B', '-m', 'pip', 'check'], options)
|
||||
if (entries.node !== undefined) execFileSync(entries.node, ['-e', `if (process.versions.node !== ${JSON.stringify(manifest.node)}) process.exit(1)`], options)
|
||||
if (entries.pnpm !== undefined && entries.node !== undefined) execFileSync(entries.node, [entries.pnpm, '--version'], options)
|
||||
|
||||
@@ -120,14 +120,6 @@ def main():
|
||||
finally:
|
||||
reopened_workbook.close()
|
||||
assert pandas.read_excel(root / "workbook.xlsx")["Value"].iloc[0] == 42
|
||||
for file, arguments in [
|
||||
("document.docx", ["--contains", "Office 文档"]),
|
||||
("presentation.pptx", ["--contains", "Office 演示", "--count", "1"]),
|
||||
("workbook.xlsx", ["--contains", "Value", "--count", "1"]),
|
||||
]:
|
||||
checked = subprocess.run([sys.executable, "-I", "-B", sys.argv[3], str(root / file), *arguments],
|
||||
check=False, capture_output=True, text=True, timeout=30)
|
||||
assert checked.returncode == 0 and json.loads(checked.stdout)["verdict"] == "pass", checked.stdout + checked.stderr
|
||||
print("Office runtime versions and document round trips passed.")
|
||||
|
||||
|
||||
|
||||
@@ -949,7 +949,6 @@ def _smoke_sdk_authoring_cached(base_url: str, executable: Path, update_snapshot
|
||||
subprocess.run([
|
||||
str(python), "-I", "-B", str(Path(__file__).parent / "primary-runtime/smoke.py"),
|
||||
json.dumps(manifest["pythonPackages"]), manifest["python"],
|
||||
str(resources / "office-skills/scripts/check_office.py"),
|
||||
], check=True, timeout=120,
|
||||
env={name: value for name, value in os.environ.items()
|
||||
if not re.search(r"KEY|SECRET|TOKEN|PASSWORD", name, re.I)})
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
{"type":"session/title","data":{"title":"Load the Office Word, PowerPoint,","messageSeqs":[8],"source":{"kind":"fallback"}}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_skill","name":"skill","arguments":"{\"name\":\"office-docx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"stream":[{"type":"chunk","time":1790753571607,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790753571608,"index":0,"dt":[],"id":"call_office_skill","name":"skill","args":["{\"name\":\"office-docx\"}"]},{"type":"chunk","time":1790753571608,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_skill","name":"skill","arguments":"{\"name\":\"office-docx\"}"}}},{"type":"chunk","time":1790753571608,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_office_skill","name":"skill","arguments":"{\"name\":\"office-docx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_skill"},"toolCallId":"call_office_skill","content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nUse the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <document.docx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.\n\nFor routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_skill"},"toolCallId":"call_office_skill","content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nReopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_2","name":"skill","arguments":"{\"name\":\"office-pptx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"stream":[{"type":"chunk","time":1790753571639,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790753571639,"index":0,"dt":[],"id":"call_office_2","name":"skill","args":["{\"name\":\"office-pptx\"}"]},{"type":"chunk","time":1790753571639,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_2","name":"skill","arguments":"{\"name\":\"office-pptx\"}"}}},{"type":"chunk","time":1790753571639,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_office_2","name":"skill","arguments":"{\"name\":\"office-pptx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_2"},"toolCallId":"call_office_2","content":[{"type":"text","text":"<skill_content name=\"office-pptx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-pptx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# PowerPoint presentations\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and use its Python executable and bundled presentation libraries. Do not install npm or pip packages or locate a system interpreter for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts and output files in the task workspace. The runtime and skill directory contain shared read-only resources. Match the requested slide language and the supplied presentation's design when editing it.\n\n## Create and edit\n\nUse `python-pptx` to inspect or modify an existing presentation. Inspect slide layouts, text runs, images, tables, and charts before editing. Change only the requested content, preserve mixed text formatting, and save to a new file unless the user requests an in-place edit. Rebuilding slides can discard unsupported animation, SmartArt, or other extension content.\n\nFor a new deck, use `python-pptx` with editable text, tables, and charts. Use local image assets rather than network-dependent image URLs. Set slide dimensions, text sizes, and chart data explicitly.\n\nA minimal editable deck, run with the selected Python executable:\n\n```python\nfrom pptx import Presentation\nfrom pptx.chart.data import CategoryChartData\nfrom pptx.enum.chart import XL_CHART_TYPE\nfrom pptx.util import Inches, Pt\n\npresentation = Presentation()\npresentation.slide_width = Inches(13.333)\npresentation.slide_height = Inches(7.5)\nslide = presentation.slides.add_slide(presentation.slide_layouts[6])\ntitle = slide.shapes.add_textbox(Inches(0.6), Inches(0.4), Inches(12), Inches(0.8))\nrun = title.text_frame.paragraphs[0].add_run()\nrun.text = \"Quarterly report\"\nrun.font.size = Pt(30)\ndata = CategoryChartData()\ndata.categories = [\"Q1\", \"Q2\"]\ndata.add_series(\"Revenue\", [12, 18])\nslide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED,\n Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.8), data)\npresentation.save(\"report.pptx\")\n```\n\nUse `Inches` or `Cm` for positions and sizes and `Pt` for font sizes. To edit a generated title while retaining its other slides and charts:\n\n```python\nfrom pptx import Presentation\n\npresentation = Presentation(\"report.pptx\")\nfor shape in presentation.slides[0].shapes:\n if shape.has_text_frame and shape.text == \"Quarterly report\":\n shape.text_frame.paragraphs[0].runs[0].text = \"Quarterly results\"\npresentation.save(\"report-edited.pptx\")\n```\n\nCheck that text and images fit the slide dimensions, titles form a useful sequence, and chart labels agree with source values. Paragraph alignment does not move a text box: when a title must be centered on the slide, center both its paragraph and the text box against `presentation.slide_width`, then reopen to verify both. A native chart's embedded workbook is part of the deliverable and must contain the intended data. Library support for writing PPTX is not a rendering engine or a guarantee that every PowerPoint feature survives editing.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <presentation.pptx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships and reports slide count and extracted text. Use repeated `--contains TEXT` arguments for required slide text and `--count N` for a requested slide count; `--contains` excludes chart text and speaker notes. Reopen the file to check the requested edits, chart data, and notes. Structural success does not establish text fit, alignment, readable contrast, or rendering fidelity.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nDeliver after the requested content and structural checks pass. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changes uLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_2"},"toolCallId":"call_office_2","content":[{"type":"text","text":"<skill_content name=\"office-pptx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-pptx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# PowerPoint presentations\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and use its Python executable and bundled presentation libraries. Do not install npm or pip packages or locate a system interpreter for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts and output files in the task workspace. The runtime and skill directory contain shared read-only resources. Match the requested slide language and the supplied presentation's design when editing it.\n\n## Create and edit\n\nUse `python-pptx` to inspect or modify an existing presentation. Inspect slide layouts, text runs, images, tables, and charts before editing. Change only the requested content, preserve mixed text formatting, and save to a new file unless the user requests an in-place edit. Rebuilding slides can discard unsupported animation, SmartArt, or other extension content.\n\nFor a new deck, use `python-pptx` with editable text, tables, and charts. Use local image assets rather than network-dependent image URLs. Set slide dimensions, text sizes, and chart data explicitly.\n\nA minimal editable deck, run with the selected Python executable:\n\n```python\nfrom pptx import Presentation\nfrom pptx.chart.data import CategoryChartData\nfrom pptx.enum.chart import XL_CHART_TYPE\nfrom pptx.util import Inches, Pt\n\npresentation = Presentation()\npresentation.slide_width = Inches(13.333)\npresentation.slide_height = Inches(7.5)\nslide = presentation.slides.add_slide(presentation.slide_layouts[6])\ntitle = slide.shapes.add_textbox(Inches(0.6), Inches(0.4), Inches(12), Inches(0.8))\nrun = title.text_frame.paragraphs[0].add_run()\nrun.text = \"Quarterly report\"\nrun.font.size = Pt(30)\ndata = CategoryChartData()\ndata.categories = [\"Q1\", \"Q2\"]\ndata.add_series(\"Revenue\", [12, 18])\nslide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED,\n Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.8), data)\npresentation.save(\"report.pptx\")\n```\n\nUse `Inches` or `Cm` for positions and sizes and `Pt` for font sizes. To edit a generated title while retaining its other slides and charts:\n\n```python\nfrom pptx import Presentation\n\npresentation = Presentation(\"report.pptx\")\nfor shape in presentation.slides[0].shapes:\n if shape.has_text_frame and shape.text == \"Quarterly report\":\n shape.text_frame.paragraphs[0].runs[0].text = \"Quarterly results\"\npresentation.save(\"report-edited.pptx\")\n```\n\nCheck that text and images fit the slide dimensions, titles form a useful sequence, and chart labels agree with source values. Paragraph alignment does not move a text box: when a title must be centered on the slide, center both its paragraph and the text box against `presentation.slide_width`, then reopen to verify both. A native chart's embedded workbook is part of the deliverable and must contain the intended data. Library support for writing PPTX is not a rendering engine or a guarantee that every PowerPoint feature survives editing.\n\n## Check and deliver\n\nReopen the saved presentation with python-pptx to verify the requested slide count, content, formatting, chart data, and notes, including unchanged content that must be preserved. These checks do not establish text fit, readable contrast, or rendering fidelity.\n\nDeliver after the requested edits are verified. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changes unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report-edited.pptx\"}]})` with the actual final PPTX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and leave intermediate images and reports out of delivery unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[20],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":2}}
|
||||
{"type":"step/start","data":{"turn":1,"step":3}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_3","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"stream":[{"type":"chunk","time":1790753571666,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790753571666,"index":0,"dt":[],"id":"call_office_3","name":"skill","args":["{\"name\":\"office-xlsx\"}"]},{"type":"chunk","time":1790753571666,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_3","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}},{"type":"chunk","time":1790753571666,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":3,"callId":"call_office_3","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_3"},"toolCallId":"call_office_3","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nRun the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the uLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_3"},"toolCallId":"call_office_3","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nReopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\n\nLoad `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\n\nCall `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:10}}"}},"sourceEventSeqs":[25],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":3}}
|
||||
{"type":"step/start","data":{"turn":1,"step":4}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_4","name":"read","arguments":"{\"file_path\":\"office-skills/office/references/sidecar.md\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:11}}"},"stream":[{"type":"chunk","time":1790753571694,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790753571694,"index":0,"dt":[],"id":"call_office_4","name":"read","args":["{\"file_path\":\"office-skills/office/references/sidecar.md\"}"]},{"type":"chunk","time":1790753571695,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_4","name":"read","arguments":"{\"file_path\":\"office-skills/office/references/sidecar.md\"}"}}},{"type":"chunk","time":1790753571695,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
{"type":"step/start","data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_2","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"stream":[{"type":"chunk","time":1791559898453,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559898453,"index":0,"dt":[],"id":"call_office_2","name":"skill","args":["{\"name\":\"office-xlsx\"}"]},{"type":"chunk","time":1791559898453,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_2","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}},{"type":"chunk","time":1791559898453,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_office_2","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_2"},"toolCallId":"call_office_2","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nRun the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the uLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_2"},"toolCallId":"call_office_2","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nReopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\n\nLoad `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\n\nCall `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[20],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":2}}
|
||||
{"type":"step/start","data":{"turn":1,"step":3}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_3","name":"skill","arguments":"{\"name\":\"office-recalculate\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"stream":[{"type":"chunk","time":1791559898470,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559898470,"index":0,"dt":[],"id":"call_office_3","name":"skill","args":["{\"name\":\"office-recalculate\"}"]},{"type":"chunk","time":1791559898470,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_3","name":"skill","arguments":"{\"name\":\"office-recalculate\"}"}}},{"type":"chunk","time":1791559898470,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_2","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-docx\\\"}));\",\"description\":\"Load task instructions\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"stream":[{"type":"chunk","time":1791781292279,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791781292279,"index":0,"dt":[],"id":"call_office_2","name":"run_code","args":["{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-docx\\\"}));\",\"description\":\"Load task instructions\"}"]},{"type":"chunk","time":1791781292279,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_2","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-docx\\\"}));\",\"description\":\"Load task instructions\"}"}}},{"type":"chunk","time":1791781292279,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_office_2","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-docx\\\"}));\",\"description\":\"Load task instructions\"}"}}
|
||||
{"type":"tool/ptc-dispatch-start","data":{"rootCallId":"call_office_2","parentCallId":"call_office_2","subCallId":"call_office_2:ptc:1","name":"skill","arguments":{"name":"office-docx"}}}
|
||||
{"type":"tool/ptc-dispatch","data":{"rootCallId":"call_office_2","parentCallId":"call_office_2","subCallId":"call_office_2:ptc:1","name":"skill","arguments":{"name":"office-docx"},"isError":false,"content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nUse the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <document.docx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.\n\nFor routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}]}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_2"},"toolCallId":"call_office_2","content":[{"type":"text","text":"{\n name: 'office-docx',\n provider: 'dsh-office',\n resourceBase: {\n kind: 'directory',\n path: '{{cwd}}/office-skills/office-docx'\n },\n content: '# Word documents\\n' +\n '\\n' +\n 'Use `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\\n' +\n '\\n' +\n \"Keep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\\n\" +\n '\\n' +\n 'Name Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\\n' +\n '\\n' +\n '## Create and edit\\n' +\n '\\n' +\n 'For text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\\n' +\n '\\n' +\n 'Use paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\\n' +\n '\\n' +\n 'python-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\\n' +\n '\\n' +\n '## Check and deliver\\n' +\n '\\n' +\n 'Use the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.\\n' +\n '\\n' +\n '```text\\n' +\n '\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <document.docx> --out <checks.json>\\n' +\n '```\\n' +\n '\\n' +\n \"It checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.\\n\" +\n '\\n' +\n 'For routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.\\n' +\n '\\n' +\n 'Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\\n' +\n '\\n' +\n 'Call `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session\\'s supported file delivery method.'\n}"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[Line truncated
|
||||
{"type":"tool/ptc-dispatch","data":{"rootCallId":"call_office_2","parentCallId":"call_office_2","subCallId":"call_office_2:ptc:1","name":"skill","arguments":{"name":"office-docx"},"isError":false,"content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nReopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}]}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_2"},"toolCallId":"call_office_2","content":[{"type":"text","text":"{\n name: 'office-docx',\n provider: 'dsh-office',\n resourceBase: {\n kind: 'directory',\n path: '{{cwd}}/office-skills/office-docx'\n },\n content: '# Word documents\\n' +\n '\\n' +\n 'Use `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\\n' +\n '\\n' +\n \"Keep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\\n\" +\n '\\n' +\n 'Name Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\\n' +\n '\\n' +\n '## Create and edit\\n' +\n '\\n' +\n 'For text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\\n' +\n '\\n' +\n 'Use paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\\n' +\n '\\n' +\n 'python-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\\n' +\n '\\n' +\n '## Check and deliver\\n' +\n '\\n' +\n 'Reopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.\\n' +\n '\\n' +\n 'Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\\n' +\n '\\n' +\n 'Call `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session\\'s supported file delivery method.'\n}"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":2}}
|
||||
{"type":"step/start","data":{"turn":1,"step":3}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_3","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-render\\\"}));\",\"description\":\"Load task instructions\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"stream":[{"type":"chunk","time":1791781292389,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791781292389,"index":0,"dt":[],"id":"call_office_3","name":"run_code","args":["{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-render\\\"}));\",\"description\":\"Load task instructions\"}"]},{"type":"chunk","time":1791781292389,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_3","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-render\\\"}));\",\"description\":\"Load task instructions\"}"}}},{"type":"chunk","time":1791781292389,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"/office-docx Load the Office rendering tool, render page 1 of report.docx to preview, remove the rendering tool, then reply DONE."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"<system-reminder>\nA skill is a reusable set of task-specific instructions. The following skills are available in this session:\n\n<available_skills>\n- `office`: Create, edit, inspect, or convert Office documents, spreadsheets, presentations, and PDFs. Load to choose the relevant workflow.\n- `office-docx`: Create, read, edit, and validate Word documents (.docx).\n- `office-export-pdf`: Convert an Office document to a requested PDF with LibreOffice Kit.\n- `office-pptx`: Create, read, edit, and validate PowerPoint presentations (.pptx).\n- `office-recalculate`: Refresh spreadsheet formula caches and verify calculated values with LibreOffice Kit.\n- `office-render`: Render requested document images or inspect visual layout with LibreOffice Kit.\n- `office-xlsx`: Read, create, edit, and validate Excel workbooks, data, and formulas (.xlsx).\n</available_skills>\n\nIf the user names a skill, or the task clearly matches a skill's description, call the `skill` tool with the exact skill name before taking task actions. Load all applicable skills, then follow their full instructions. This catalog contains summaries only; do not infer or follow a skill's instructions until it has been loaded.\nA user may also invoke a skill directly; its <skill_content> block then appears in this conversation. Follow it, and do not call the `skill` tool again for that skill.\n</system-reminder>"}],"source":{"kind":"skill-catalog","form":"catalog","entries":[{"name":"office","description":"Create, edit, inspect, or convert Office documents, spreadsheets, presentations, and PDFs. Load to choose the relevant workflow."},{"name":"office-docx","description":"Create, read, edit, and validate Word documents (.docx)."},{"name":"office-export-pdf","description":"Convert an Office document to a requested PDF with LibreOffice Kit."},{"name":"office-pptx","description":"Create, read, edit, and validate PowerPoint presentations (.pptx)."},{"name":"office-recalculate","description":"Refresh spreadsheet formula caches and verify calculated values with LibreOffice Kit."},{"name":"office-render","description":"Render requested document images or inspect visual layout with LibreOffice Kit."},{"name":"office-xlsx","description":"Read, create, edit, and validate Excel workbooks, data, and formulas (.xlsx)."}]},"role":"user","id":"{{message:4}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nUse the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <document.docx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.\n\nFor routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"source":{"kind":"skill-invocation","name":"office-docx","form":"instructions"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nReopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"source":{"kind":"skill-invocation","name":"office-docx","form":"instructions"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"}
|
||||
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}
|
||||
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
|
||||
{"type":"session/title","data":{"title":"/office-docx Load the Office rendering","messageSeqs":[8],"source":{"kind":"fallback"}}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_skill","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-xlsx\\\"}));\",\"description\":\"Use the Office workflow\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"stream":[{"type":"chunk","time":1791559901535,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559901535,"index":0,"dt":[],"id":"call_office_skill","name":"run_code","args":["{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-xlsx\\\"}));\",\"description\":\"Use the Office workflow\"}"]},{"type":"chunk","time":1791559901535,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_skill","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-xlsx\\\"}));\",\"description\":\"Use the Office workflow\"}"}}},{"type":"chunk","time":1791559901535,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_office_skill","name":"run_code","arguments":"{\"code\":\"console.log(await tools.skill({\\\"name\\\":\\\"office-xlsx\\\"}));\",\"description\":\"Use the Office workflow\"}"}}
|
||||
{"type":"tool/ptc-dispatch-start","data":{"rootCallId":"call_office_skill","parentCallId":"call_office_skill","subCallId":"call_office_skill:ptc:1","name":"skill","arguments":{"name":"office-xlsx"}}}
|
||||
{"type":"tool/ptc-dispatch","data":{"rootCallId":"call_office_skill","parentCallId":"call_office_skill","subCallId":"call_office_skill:ptc:1","name":"skill","arguments":{"name":"office-xlsx"},"isError":false,"content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nRun the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering evLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_skill"},"toolCallId":"call_office_skill","content":[{"type":"text","text":"{\n name: 'office-xlsx',\n provider: 'dsh-office',\n resourceBase: {\n kind: 'directory',\n path: '{{cwd}}/office-skills/office-xlsx'\n },\n content: '# Excel workbooks\\n' +\n '\\n' +\n 'Follow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\\n' +\n '\\n' +\n 'Keep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\\n' +\n '\\n' +\n '## Read and modify\\n' +\n '\\n' +\n 'Use `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\\n' +\n '\\n' +\n 'Use pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\\n' +\n '\\n' +\n 'For a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\\n' +\n '\\n' +\n '```python\\n' +\n 'from openpyxl import Workbook\\n' +\n 'from openpyxl.styles import Font\\n' +\n '\\n' +\n 'workbook = Workbook()\\n' +\n 'sheet = workbook.active\\n' +\n 'sheet.title = \"Revenue\"\\n' +\n 'for row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\\n' +\n ' sheet.append(row)\\n' +\n 'for cell in sheet[1]:\\n' +\n ' cell.font = Font(bold=True)\\n' +\n 'sheet.column_dimensions[\"A\"].width = 18\\n' +\n 'sheet.column_dimensions[\"B\"].width = 18\\n' +\n 'workbook.save(\"report.xlsx\")\\n' +\n '```\\n' +\n '\\n' +\n 'Preserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\\n' +\n '\\n' +\n 'Writing a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\\n' +\n '\\n' +\n 'Do not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\\n' +\n '\\n' +\n '## Check and deliver\\n' +\n '\\n' +\n 'Run the shared structural checker when `office-check` is available:\\n' +\n '\\n' +\n \"Run the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\\n\" +\n '\\n' +\n 'In PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\\n' +\n '\\n' +\n '```text\\n' +\n '\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\\n' +\n '```\\n' +\n '\\n' +\n \"It checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\\n\" +\n '\\n' +\n 'If the Python checker cannot run, use an already configured environment to check the ZIP/XMLine truncated
|
||||
{"type":"tool/ptc-dispatch","data":{"rootCallId":"call_office_skill","parentCallId":"call_office_skill","subCallId":"call_office_skill:ptc:1","name":"skill","arguments":{"name":"office-xlsx"},"isError":false,"content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nReopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\n\nLoad `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\n\nCall `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}]}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_skill"},"toolCallId":"call_office_skill","content":[{"type":"text","text":"{\n name: 'office-xlsx',\n provider: 'dsh-office',\n resourceBase: {\n kind: 'directory',\n path: '{{cwd}}/office-skills/office-xlsx'\n },\n content: '# Excel workbooks\\n' +\n '\\n' +\n 'Follow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\\n' +\n '\\n' +\n 'Keep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\\n' +\n '\\n' +\n '## Read and modify\\n' +\n '\\n' +\n 'Use `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\\n' +\n '\\n' +\n 'Use pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\\n' +\n '\\n' +\n 'For a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\\n' +\n '\\n' +\n '```python\\n' +\n 'from openpyxl import Workbook\\n' +\n 'from openpyxl.styles import Font\\n' +\n '\\n' +\n 'workbook = Workbook()\\n' +\n 'sheet = workbook.active\\n' +\n 'sheet.title = \"Revenue\"\\n' +\n 'for row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\\n' +\n ' sheet.append(row)\\n' +\n 'for cell in sheet[1]:\\n' +\n ' cell.font = Font(bold=True)\\n' +\n 'sheet.column_dimensions[\"A\"].width = 18\\n' +\n 'sheet.column_dimensions[\"B\"].width = 18\\n' +\n 'workbook.save(\"report.xlsx\")\\n' +\n '```\\n' +\n '\\n' +\n 'Preserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\\n' +\n '\\n' +\n 'Writing a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\\n' +\n '\\n' +\n 'Do not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\\n' +\n '\\n' +\n '## Check and deliver\\n' +\n '\\n' +\n 'Reopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\\n' +\n '\\n' +\n \"Load `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\\n\" +\n '\\n' +\n 'Load `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\\n' +\n '\\n' +\n 'Call `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source Line truncated
|
||||
{"type":"step/end","data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_2","name":"run_code","arguments":"{\"code\":\"console.log(await tools.office_tools({\\\"action\\\":\\\"load\\\"}));\",\"description\":\"Use the Office workflow\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"stream":[{"type":"chunk","time":1791781540339,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791781540339,"index":0,"dt":[],"id":"call_office_2","name":"run_code","args":["{\"code\":\"console.log(await tools.office_tools({\\\"action\\\":\\\"load\\\"}));\",\"description\":\"Use the Office workflow\"}"]},{"type":"chunk","time":1791781540339,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_2","name":"run_code","arguments":"{\"code\":\"console.log(await tools.office_tools({\\\"action\\\":\\\"load\\\"}));\",\"description\":\"Use the Office workflow\"}"}}},{"type":"chunk","time":1791781540339,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"/office-docx Load the Office rendering tool, render page 1 of report.docx to preview, remove the rendering tool, then reply DONE."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"<system-reminder>\nA skill is a reusable set of task-specific instructions. The following skills are available in this session:\n\n<available_skills>\n- `office`: Create, edit, inspect, or convert Office documents, spreadsheets, presentations, and PDFs. Load to choose the relevant workflow.\n- `office-docx`: Create, read, edit, and validate Word documents (.docx).\n- `office-export-pdf`: Convert an Office document to a requested PDF with LibreOffice Kit.\n- `office-pptx`: Create, read, edit, and validate PowerPoint presentations (.pptx).\n- `office-recalculate`: Refresh spreadsheet formula caches and verify calculated values with LibreOffice Kit.\n- `office-render`: Render requested document images or inspect visual layout with LibreOffice Kit.\n- `office-xlsx`: Read, create, edit, and validate Excel workbooks, data, and formulas (.xlsx).\n</available_skills>\n\nIf the user names a skill, or the task clearly matches a skill's description, call the `skill` tool with the exact skill name before taking task actions. Load all applicable skills, then follow their full instructions. This catalog contains summaries only; do not infer or follow a skill's instructions until it has been loaded.\nA user may also invoke a skill directly; its <skill_content> block then appears in this conversation. Follow it, and do not call the `skill` tool again for that skill.\n</system-reminder>"}],"source":{"kind":"skill-catalog","form":"catalog","entries":[{"name":"office","description":"Create, edit, inspect, or convert Office documents, spreadsheets, presentations, and PDFs. Load to choose the relevant workflow."},{"name":"office-docx","description":"Create, read, edit, and validate Word documents (.docx)."},{"name":"office-export-pdf","description":"Convert an Office document to a requested PDF with LibreOffice Kit."},{"name":"office-pptx","description":"Create, read, edit, and validate PowerPoint presentations (.pptx)."},{"name":"office-recalculate","description":"Refresh spreadsheet formula caches and verify calculated values with LibreOffice Kit."},{"name":"office-render","description":"Render requested document images or inspect visual layout with LibreOffice Kit."},{"name":"office-xlsx","description":"Read, create, edit, and validate Excel workbooks, data, and formulas (.xlsx)."}]},"role":"user","id":"{{message:4}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nUse the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <document.docx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.\n\nFor routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"source":{"kind":"skill-invocation","name":"office-docx","form":"instructions"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"}
|
||||
{"type":"user/message","data":{"content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nReopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"source":{"kind":"skill-invocation","name":"office-docx","form":"instructions"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"}
|
||||
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}
|
||||
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
|
||||
{"type":"session/title","data":{"title":"/office-docx Load the Office rendering","messageSeqs":[8],"source":{"kind":"fallback"}}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_skill","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"stream":[{"type":"chunk","time":1791559900742,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559900742,"index":0,"dt":[],"id":"call_office_skill","name":"skill","args":["{\"name\":\"office-xlsx\"}"]},{"type":"chunk","time":1791559900742,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_skill","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}},{"type":"chunk","time":1791559900742,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_office_skill","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_skill"},"toolCallId":"call_office_skill","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nRun the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unleLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_office_skill"},"toolCallId":"call_office_skill","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nReopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\n\nLoad `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\n\nCall `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[16],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_office_2","name":"office_tools","arguments":"{\"action\":\"load\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"stream":[{"type":"chunk","time":1791559900760,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559900760,"index":0,"dt":[],"id":"call_office_2","name":"office_tools","args":["{\"action\":\"load\"}"]},{"type":"chunk","time":1791559900760,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_office_2","name":"office_tools","arguments":"{\"action\":\"load\"}"}}},{"type":"chunk","time":1791559900760,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
{"type":"session/title","data":{"title":"请先加载 office-docx、office-pptx","messageSeqs":[8],"source":{"kind":"fallback"}}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user asks me to load three skills and answer workflow questions only. Let me load them."},{"type":"tool-call","id":"call_00_2jAvhW74YFzV34o6WcLH6654","name":"skill","arguments":"{\"name\": \"office-docx\"}"},{"type":"tool-call","id":"call_01_I6imo0g6ZL4X4MdJjbZ71052","name":"skill","arguments":"{\"name\": \"office-pptx\"}"},{"type":"tool-call","id":"call_02_uzWu2TTyXsHOQJ6OzTiz1019","name":"skill","arguments":"{\"name\": \"office-xlsx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"usage":{"inputTokens":7253,"outputTokens":118,"totalTokens":7371,"cacheReadTokens":0,"reasoningTokens":19},"stream":[{"type":"chunk","time":1791559904623,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791559904624,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," asks"," me"," to"," load"," three"," skills"," and"," answer"," workflow"," questions"," only","."," Let"," me"," load"," them","."]},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559904624,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_2jAvhW74YFzV34o6WcLH6654","name":"skill","args":["","{","\"","name","\"",": ","\"","office","-d","oc","x","\"","}"]},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-start","index":2,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559904624,"index":2,"dt":[0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_01_I6imo0g6ZL4X4MdJjbZ71052","name":"skill","args":["","{","\"","name","\"",": ","\"","office","-","pp","tx","\"","}"]},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-start","index":3,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559904624,"index":3,"dt":[0,0,0,0,0,0,0,0,0,0,0],"id":"call_02_uzWu2TTyXsHOQJ6OzTiz1019","name":"skill","args":["","{","\"","name","\"",": ","\"","office","-x","lsx","\"","}"]},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user asks me to load three skills and answer workflow questions only. Let me load them."}}},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_2jAvhW74YFzV34o6WcLH6654","name":"skill","arguments":"{\"name\": \"office-docx\"}"}}},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-end","index":2,"block":{"type":"tool-call","id":"call_01_I6imo0g6ZL4X4MdJjbZ71052","name":"skill","arguments":"{\"name\": \"office-pptx\"}"}}},{"type":"chunk","time":1791559904624,"chunk":{"type":"block-end","index":3,"block":{"type":"tool-call","id":"call_02_uzWu2TTyXsHOQJ6OzTiz1019","name":"skill","arguments":"{\"name\": \"office-xlsx\"}"}}},{"type":"chunk","time":1791559904624,"chunk":{"type":"usage","usage":{"inputTokens":7253,"outputTokens":118,"totalTokens":7371,"cacheReadTokens":0,"reasoningTokens":19}}},{"type":"chunk","time":1791559904624,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_2jAvhW74YFzV34o6WcLH6654","name":"skill","arguments":"{\"name\": \"office-docx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_2jAvhW74YFzV34o6WcLH6654"},"toolCallId":"call_00_2jAvhW74YFzV34o6WcLH6654","content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nUse the full loaded skill result, including `resourceBase.path`, for script paths. In PTC, print or return the full result rather than only `.content`. Run the shared Python checker once per saved version; `<skill-directory>` is that resource path. Do not search other directories for the checker. In PowerShell, prefix the quoted Python executable with `&`.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <document.docx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports paragraphs, logical table dimensions, and sections. Optional `--contains TEXT` arguments assert required text. A successful structural check does not verify pagination, clipping, fonts, or visual appearance. Compare the summary and reopened document with the user's request, including unchanged content that matters to an edit.\n\nFor routine text edits, the shared checker and targeted content/formatting verification are sufficient; deliver when both pass. Do not dump or unpack OOXML, enumerate styles, inspect document properties, or compare whole packages for reassurance. Use package-level investigation only for a concrete validation failure, ambiguous edit target, unsupported feature, or explicit user requirement. Repair script/import errors before continuing. If the checker cannot run, report the structural-validation limit.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_2jAvhW74YFzV34o6WcLH6654"},"toolCallId":"call_00_2jAvhW74YFzV34o6WcLH6654","content":[{"type":"text","text":"<skill_content name=\"office-docx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-docx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Word documents\n\nUse `python-docx` for DOCX creation and ordinary edits. Follow an explicit user or applicable AGENTS.md requirement for a project environment or another library. Otherwise call `load_workspace_dependencies` and execute the returned Python path with its bundled libraries. Do not install packages or discover a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep source scripts, intermediate files, and final documents in the task workspace; the runtime and this skill directory are read-only resources. Use the user's requested language and preserve an existing document's design unless a redesign is requested.\n\nName Python scripts for their task, such as `edit_docx.py`; avoid module names such as `inspect.py`, `docx.py`, or `zipfile.py` that shadow imported libraries.\n\n## Create and edit\n\nFor text edits, locate the target by its text or position and inspect only its runs and formatting. A title can be an ordinary paragraph without a Title style or document-property title. Update the relevant runs; assigning paragraph `.text` destroys run formatting. Save a new file unless an in-place edit is requested. Read other structures only when the edit involves them; rebuilding a document can lose unsupported features.\n\nUse paragraph styles for headings and body text. Size tables for the section that contains them, and account for merged cells and nested tables. Chinese, Japanese, and Korean text may need an explicit `w:eastAsia` font assignment in addition to `run.font.name`; font names alone do not establish glyph availability or rendered appearance.\n\npython-docx does not paginate or render documents. Do not represent ordinary replacement, colored text, or comments as tracked changes. When real revisions or unsupported OOXML features matter, preserve their package parts and verify the requested operation rather than silently discarding them.\n\n## Check and deliver\n\nReopen the saved document with python-docx and verify the requested content, related formatting, and unchanged content that must be preserved. Deliver when these checks pass. Investigate package-level details only for a concrete failure, ambiguous edit target, unsupported feature, or explicit user requirement.\n\nCreating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection. When styling, font color, spacing, sizing, or text alignment is the requested edit, load `office-render` and inspect the changed page even without a separate visual-check request, unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report.docx\"}]})` with the actual final DOCX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and do not present temporary QA reports unless requested. If `present` is unavailable, provide the final workspace path using the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_01_I6imo0g6ZL4X4MdJjbZ71052","name":"skill","arguments":"{\"name\": \"office-pptx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_01_I6imo0g6ZL4X4MdJjbZ71052"},"toolCallId":"call_01_I6imo0g6ZL4X4MdJjbZ71052","content":[{"type":"text","text":"<skill_content name=\"office-pptx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-pptx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# PowerPoint presentations\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and use its Python executable and bundled presentation libraries. Do not install npm or pip packages or locate a system interpreter for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts and output files in the task workspace. The runtime and skill directory contain shared read-only resources. Match the requested slide language and the supplied presentation's design when editing it.\n\n## Create and edit\n\nUse `python-pptx` to inspect or modify an existing presentation. Inspect slide layouts, text runs, images, tables, and charts before editing. Change only the requested content, preserve mixed text formatting, and save to a new file unless the user requests an in-place edit. Rebuilding slides can discard unsupported animation, SmartArt, or other extension content.\n\nFor a new deck, use `python-pptx` with editable text, tables, and charts. Use local image assets rather than network-dependent image URLs. Set slide dimensions, text sizes, and chart data explicitly.\n\nA minimal editable deck, run with the selected Python executable:\n\n```python\nfrom pptx import Presentation\nfrom pptx.chart.data import CategoryChartData\nfrom pptx.enum.chart import XL_CHART_TYPE\nfrom pptx.util import Inches, Pt\n\npresentation = Presentation()\npresentation.slide_width = Inches(13.333)\npresentation.slide_height = Inches(7.5)\nslide = presentation.slides.add_slide(presentation.slide_layouts[6])\ntitle = slide.shapes.add_textbox(Inches(0.6), Inches(0.4), Inches(12), Inches(0.8))\nrun = title.text_frame.paragraphs[0].add_run()\nrun.text = \"Quarterly report\"\nrun.font.size = Pt(30)\ndata = CategoryChartData()\ndata.categories = [\"Q1\", \"Q2\"]\ndata.add_series(\"Revenue\", [12, 18])\nslide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED,\n Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.8), data)\npresentation.save(\"report.pptx\")\n```\n\nUse `Inches` or `Cm` for positions and sizes and `Pt` for font sizes. To edit a generated title while retaining its other slides and charts:\n\n```python\nfrom pptx import Presentation\n\npresentation = Presentation(\"report.pptx\")\nfor shape in presentation.slides[0].shapes:\n if shape.has_text_frame and shape.text == \"Quarterly report\":\n shape.text_frame.paragraphs[0].runs[0].text = \"Quarterly results\"\npresentation.save(\"report-edited.pptx\")\n```\n\nCheck that text and images fit the slide dimensions, titles form a useful sequence, and chart labels agree with source values. Paragraph alignment does not move a text box: when a title must be centered on the slide, center both its paragraph and the text box against `presentation.slide_width`, then reopen to verify both. A native chart's embedded workbook is part of the deliverable and must contain the intended data. Library support for writing PPTX is not a rendering engine or a guarantee that every PowerPoint feature survives editing.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <presentation.pptx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships and reports slide count and extracted text. Use repeated `--contains TEXT` arguments for required slide text and `--count N` for a requested slide count; `--contains` excludes chart text and speaker notes. Reopen the file to check the requested edits, chart data, and notes. Structural success does not establish text fit, alignment, readable contrast, or rendering fidelity.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nDeliver after the requested content and structural checks pass. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, sLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_01_I6imo0g6ZL4X4MdJjbZ71052"},"toolCallId":"call_01_I6imo0g6ZL4X4MdJjbZ71052","content":[{"type":"text","text":"<skill_content name=\"office-pptx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-pptx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# PowerPoint presentations\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and use its Python executable and bundled presentation libraries. Do not install npm or pip packages or locate a system interpreter for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts and output files in the task workspace. The runtime and skill directory contain shared read-only resources. Match the requested slide language and the supplied presentation's design when editing it.\n\n## Create and edit\n\nUse `python-pptx` to inspect or modify an existing presentation. Inspect slide layouts, text runs, images, tables, and charts before editing. Change only the requested content, preserve mixed text formatting, and save to a new file unless the user requests an in-place edit. Rebuilding slides can discard unsupported animation, SmartArt, or other extension content.\n\nFor a new deck, use `python-pptx` with editable text, tables, and charts. Use local image assets rather than network-dependent image URLs. Set slide dimensions, text sizes, and chart data explicitly.\n\nA minimal editable deck, run with the selected Python executable:\n\n```python\nfrom pptx import Presentation\nfrom pptx.chart.data import CategoryChartData\nfrom pptx.enum.chart import XL_CHART_TYPE\nfrom pptx.util import Inches, Pt\n\npresentation = Presentation()\npresentation.slide_width = Inches(13.333)\npresentation.slide_height = Inches(7.5)\nslide = presentation.slides.add_slide(presentation.slide_layouts[6])\ntitle = slide.shapes.add_textbox(Inches(0.6), Inches(0.4), Inches(12), Inches(0.8))\nrun = title.text_frame.paragraphs[0].add_run()\nrun.text = \"Quarterly report\"\nrun.font.size = Pt(30)\ndata = CategoryChartData()\ndata.categories = [\"Q1\", \"Q2\"]\ndata.add_series(\"Revenue\", [12, 18])\nslide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED,\n Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.8), data)\npresentation.save(\"report.pptx\")\n```\n\nUse `Inches` or `Cm` for positions and sizes and `Pt` for font sizes. To edit a generated title while retaining its other slides and charts:\n\n```python\nfrom pptx import Presentation\n\npresentation = Presentation(\"report.pptx\")\nfor shape in presentation.slides[0].shapes:\n if shape.has_text_frame and shape.text == \"Quarterly report\":\n shape.text_frame.paragraphs[0].runs[0].text = \"Quarterly results\"\npresentation.save(\"report-edited.pptx\")\n```\n\nCheck that text and images fit the slide dimensions, titles form a useful sequence, and chart labels agree with source values. Paragraph alignment does not move a text box: when a title must be centered on the slide, center both its paragraph and the text box against `presentation.slide_width`, then reopen to verify both. A native chart's embedded workbook is part of the deliverable and must contain the intended data. Library support for writing PPTX is not a rendering engine or a guarantee that every PowerPoint feature survives editing.\n\n## Check and deliver\n\nReopen the saved presentation with python-pptx to verify the requested slide count, content, formatting, chart data, and notes, including unchanged content that must be preserved. These checks do not establish text fit, readable contrast, or rendering fidelity.\n\nDeliver after the requested edits are verified. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changes unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report-edited.pptx\"}]})` with the actual final PPTX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and leave intermediate images and reports out of delivery unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[17],"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_02_uzWu2TTyXsHOQJ6OzTiz1019","name":"skill","arguments":"{\"name\": \"office-xlsx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_02_uzWu2TTyXsHOQJ6OzTiz1019"},"toolCallId":"call_02_uzWu2TTyXsHOQJ6OzTiz1019","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nRun the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_02_uzWu2TTyXsHOQJ6OzTiz1019"},"toolCallId":"call_02_uzWu2TTyXsHOQJ6OzTiz1019","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nReopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\n\nLoad `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\n\nCall `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[1Line truncated
|
||||
{"type":"step/end","data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants workflow-only answer. Note: skill instructions mention `load_workspace_dependencies` and `render_document` and `present` — but current tool list doesn't include those. The user says \"仅根据 skill 指令及当前工具清单确认工作流\" — based on skill instructions and current tool list. Current tools: bash, create_goal, edit, exit_plan_mode, get_goal, glob, grep, interrupt_agent, job_kill, job_list, job_output, list_agents, read, read_image, send_message, skill, subagent, subagent_fork, todo_write, update_goal, web_fetch, web_search, workflow, write.\n\nSo `load_workspace_dependencies`, `render_document`, `present` are NOT available. The user premise: Desktop environment already configured with packaging Python and Office libs. So missing renderer does not block delivery — skills say if rendering unavailable, deliver and report the inspection limit. Explicitly \"do not require the user to install a renderer\".\n\nPPTX create and edit: both python-pptx (create new deck python-pptx; edit existing python-pptx).\n\nChecks before delivery: run shared checker `check_office.py` via Python executable: ZIP/XML integrity, relationships, counts; --contains, --count; reopen file. Does the checker script exist? User said don't check host env, don't run commands. So just workflow.\n\nCannot claim visual inspection: only if render_document available and read_image done; here render tool unavailable → must state visual layout was not inspected. Cannot claim Excel formula recalculation: openpyxl doesn't evaluate; checker doesn't calculate; LibreOffice preview doesn't update cached formulas; must state results require recalculation in a spreadsheet app. Must not report cached values as newly calculated.\n\nAlso note: since load_workspace_dependencies is unavailable, use the already-configured Desktop environment's Python (per skill fallback: \"If the tool is unavailable, use an already configured environment\").\n\nAnswer in Chinese, brief, workflow only. No commands run.\n\nStructure:\n1. 工作流确认前提\n2. 缺渲染工具是否阻止交付 - no\n3. PPTX 库\n4. 交付前检查\n5. 能声称什么/不能\n\nKeep concise."},{"type":"text","text":"已加载三个 skill。仅依据 skill 指令与当前会话工具清单(无 `load_workspace_dependencies`、无 `render_document`、无 `present`,仅有 bash / read / read_image / write / edit / glob / grep / subagent 等)确认工作流如下。\n\n## 1. 缺渲染工具是否阻止交付\n不阻止。三个 skill 一致规定:渲染/视觉检查是可选增强项;渲染工具不可用或失败时,应保留可用的成品、完成结构与内容检查,并简要说明\"未做视觉布局检查\",且不得要求用户去安装渲染器。\n- 因此 DOCX / PPTX / XLSX 均可正常交付。\n- 默认交付方式:`present` 不可用,改用当前会话支持的文件交付方式(提供工作区内最终文件的真实路径)。\n- 因 `load_workspace_dependencies` 不可用,按 skill 的兜底规则,使用\"已配置好的\"Desktop Python 环境,不安装依赖、不搜寻系统 Python。\n\n## 2. PPTX 新建与编辑分别用什么库\n两者都是 `python-pptx`:\n- 新建:`Presentation()`,显式设置 `slide_width/slide_height`、字号(`Pt`)、位置尺寸(`Inches`/`Cm`);表格、图表用可编辑的原生对象,图片用本地资源而非网络 URL;图表数据写进内嵌 workbook。\n- 编辑:打开已有文件后先检查 slide layouts、text runs、图片、表格、图表,只改请求的内容,保留混合格式,另存为新文件(除非用户要求原地修改);不整片重建,以免丢失动画/SmartArt 等扩展内容。\n\n## 3. 交付前的结构与内容检查\n统一先跑共享检查器:\n`<python> <skill-directory>/../scripts/check_office.py <file> --out <checks.json>`\n- 三者共通:ZIP/XML 完整性、内部关系。\n- DOCX:`--contains TEXT`;报告段落、逻辑表格尺寸、节;再重开文档核对请求内容及需保留的未改动内容。\n- PPTX:`--contains TEXT`(不含图表文本与备注)、`--count N` 核对页数;报告页数与提取文本;重开核对改动、图表数据、备注;抽查文字/图片是否超出页面尺寸、标题顺序、图表标签与源数据一致。\n- XLSX:`--contains TEXT`(仅字符串单元格与表名,不含数值)、`--count N`;报告表名、非空单元格数、公式数;另用 openpyxl 单独核对数值、类型、公式、样式与合计;含公式时用 `data_only=False` 保存。\n- 结论:结构检查通过 ≠ 排版/视觉通过,不能互相替代。\n\n## 4. 能否声称做了视觉检查\n不能。本会话没有 `render_document`,无法产出 `pages[].imagePath`,也就无法用 `read_image` 看图。交付时只能做结构+内容检查Line truncated
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
{"type":"session/title","data":{"title":"Load the office-pptx and office-xlsx","messageSeqs":[8],"source":{"kind":"fallback"}}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Load the requested skill."},{"type":"tool-call","id":"call_skill_load","name":"skill","arguments":"{\"name\":\"office-pptx\"}"},{"type":"tool-call","id":"call_skill_xlsx","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"usage":{"inputTokens":100,"outputTokens":20,"cacheReadTokens":0,"reasoningTokens":5},"stream":[{"type":"chunk","time":1791559903809,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791559903809,"index":0,"dt":[],"texts":["Load the requested skill."]},{"type":"chunk","time":1791559903809,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559903809,"index":1,"dt":[],"id":"call_skill_load","name":"skill","args":["{\"name\":\"office-pptx\"}"]},{"type":"chunk","time":1791559903809,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Load the requested skill."}}},{"type":"chunk","time":1791559903809,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_skill_load","name":"skill","arguments":"{\"name\":\"office-pptx\"}"}}},{"type":"chunk","time":1791559903809,"chunk":{"type":"block-start","index":2,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791559903809,"index":2,"dt":[],"id":"call_skill_xlsx","name":"skill","args":["{\"name\":\"office-xlsx\"}"]},{"type":"chunk","time":1791559903809,"chunk":{"type":"block-end","index":2,"block":{"type":"tool-call","id":"call_skill_xlsx","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}},{"type":"chunk","time":1791559903809,"chunk":{"type":"usage","usage":{"inputTokens":100,"outputTokens":20,"cacheReadTokens":0,"reasoningTokens":5}}},{"type":"chunk","time":1791559903809,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_skill_load","name":"skill","arguments":"{\"name\":\"office-pptx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_skill_load"},"toolCallId":"call_skill_load","content":[{"type":"text","text":"<skill_content name=\"office-pptx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-pptx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# PowerPoint presentations\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and use its Python executable and bundled presentation libraries. Do not install npm or pip packages or locate a system interpreter for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts and output files in the task workspace. The runtime and skill directory contain shared read-only resources. Match the requested slide language and the supplied presentation's design when editing it.\n\n## Create and edit\n\nUse `python-pptx` to inspect or modify an existing presentation. Inspect slide layouts, text runs, images, tables, and charts before editing. Change only the requested content, preserve mixed text formatting, and save to a new file unless the user requests an in-place edit. Rebuilding slides can discard unsupported animation, SmartArt, or other extension content.\n\nFor a new deck, use `python-pptx` with editable text, tables, and charts. Use local image assets rather than network-dependent image URLs. Set slide dimensions, text sizes, and chart data explicitly.\n\nA minimal editable deck, run with the selected Python executable:\n\n```python\nfrom pptx import Presentation\nfrom pptx.chart.data import CategoryChartData\nfrom pptx.enum.chart import XL_CHART_TYPE\nfrom pptx.util import Inches, Pt\n\npresentation = Presentation()\npresentation.slide_width = Inches(13.333)\npresentation.slide_height = Inches(7.5)\nslide = presentation.slides.add_slide(presentation.slide_layouts[6])\ntitle = slide.shapes.add_textbox(Inches(0.6), Inches(0.4), Inches(12), Inches(0.8))\nrun = title.text_frame.paragraphs[0].add_run()\nrun.text = \"Quarterly report\"\nrun.font.size = Pt(30)\ndata = CategoryChartData()\ndata.categories = [\"Q1\", \"Q2\"]\ndata.add_series(\"Revenue\", [12, 18])\nslide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED,\n Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.8), data)\npresentation.save(\"report.pptx\")\n```\n\nUse `Inches` or `Cm` for positions and sizes and `Pt` for font sizes. To edit a generated title while retaining its other slides and charts:\n\n```python\nfrom pptx import Presentation\n\npresentation = Presentation(\"report.pptx\")\nfor shape in presentation.slides[0].shapes:\n if shape.has_text_frame and shape.text == \"Quarterly report\":\n shape.text_frame.paragraphs[0].runs[0].text = \"Quarterly results\"\npresentation.save(\"report-edited.pptx\")\n```\n\nCheck that text and images fit the slide dimensions, titles form a useful sequence, and chart labels agree with source values. Paragraph alignment does not move a text box: when a title must be centered on the slide, center both its paragraph and the text box against `presentation.slide_width`, then reopen to verify both. A native chart's embedded workbook is part of the deliverable and must contain the intended data. Library support for writing PPTX is not a rendering engine or a guarantee that every PowerPoint feature survives editing.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <presentation.pptx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships and reports slide count and extracted text. Use repeated `--contains TEXT` arguments for required slide text and `--count N` for a requested slide count; `--contains` excludes chart text and speaker notes. Reopen the file to check the requested edits, chart data, and notes. Structural success does not establish text fit, alignment, readable contrast, or rendering fidelity.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nDeliver after the requested content and structural checks pass. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_skill_load"},"toolCallId":"call_skill_load","content":[{"type":"text","text":"<skill_content name=\"office-pptx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-pptx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# PowerPoint presentations\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and use its Python executable and bundled presentation libraries. Do not install npm or pip packages or locate a system interpreter for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts and output files in the task workspace. The runtime and skill directory contain shared read-only resources. Match the requested slide language and the supplied presentation's design when editing it.\n\n## Create and edit\n\nUse `python-pptx` to inspect or modify an existing presentation. Inspect slide layouts, text runs, images, tables, and charts before editing. Change only the requested content, preserve mixed text formatting, and save to a new file unless the user requests an in-place edit. Rebuilding slides can discard unsupported animation, SmartArt, or other extension content.\n\nFor a new deck, use `python-pptx` with editable text, tables, and charts. Use local image assets rather than network-dependent image URLs. Set slide dimensions, text sizes, and chart data explicitly.\n\nA minimal editable deck, run with the selected Python executable:\n\n```python\nfrom pptx import Presentation\nfrom pptx.chart.data import CategoryChartData\nfrom pptx.enum.chart import XL_CHART_TYPE\nfrom pptx.util import Inches, Pt\n\npresentation = Presentation()\npresentation.slide_width = Inches(13.333)\npresentation.slide_height = Inches(7.5)\nslide = presentation.slides.add_slide(presentation.slide_layouts[6])\ntitle = slide.shapes.add_textbox(Inches(0.6), Inches(0.4), Inches(12), Inches(0.8))\nrun = title.text_frame.paragraphs[0].add_run()\nrun.text = \"Quarterly report\"\nrun.font.size = Pt(30)\ndata = CategoryChartData()\ndata.categories = [\"Q1\", \"Q2\"]\ndata.add_series(\"Revenue\", [12, 18])\nslide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED,\n Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.8), data)\npresentation.save(\"report.pptx\")\n```\n\nUse `Inches` or `Cm` for positions and sizes and `Pt` for font sizes. To edit a generated title while retaining its other slides and charts:\n\n```python\nfrom pptx import Presentation\n\npresentation = Presentation(\"report.pptx\")\nfor shape in presentation.slides[0].shapes:\n if shape.has_text_frame and shape.text == \"Quarterly report\":\n shape.text_frame.paragraphs[0].runs[0].text = \"Quarterly results\"\npresentation.save(\"report-edited.pptx\")\n```\n\nCheck that text and images fit the slide dimensions, titles form a useful sequence, and chart labels agree with source values. Paragraph alignment does not move a text box: when a title must be centered on the slide, center both its paragraph and the text box against `presentation.slide_width`, then reopen to verify both. A native chart's embedded workbook is part of the deliverable and must contain the intended data. Library support for writing PPTX is not a rendering engine or a guarantee that every PowerPoint feature survives editing.\n\n## Check and deliver\n\nReopen the saved presentation with python-pptx to verify the requested slide count, content, formatting, chart data, and notes, including unchanged content that must be preserved. These checks do not establish text fit, readable contrast, or rendering fidelity.\n\nDeliver after the requested edits are verified. Creating a file or changing content with incidental basic formatting does not require additional operations. Load `office-render` for requested images or visual inspection and for appearance-focused styling, spacing, sizing, or alignment changes unless the user explicitly skips rendering. For PDF output load `office-export-pdf`.\n\nCall `present({\"files\":[{\"path\":\"report-edited.pptx\"}]})` with the actual final PPTX path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and leave intermediate images and reports out of delivery unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_skill_xlsx","name":"skill","arguments":"{\"name\":\"office-xlsx\"}"}}
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_skill_xlsx"},"toolCallId":"call_skill_xlsx","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nRun the shared structural checker when `office-check` is available:\n\nRun the shared checker after saving. Resolve `<skill-directory>` from the loaded skill's `resourceBase.path`; do not substitute an ad hoc ZIP check when the script is available.\n\nIn PowerShell, prefix the quoted Python executable with `&`. Resolve the checker path relative to this skill directory.\n\n```text\n\"<python>\" \"<skill-directory>/../scripts/check_office.py\" <workbook.xlsx> --out <checks.json>\n```\n\nIt checks ZIP/XML integrity and internal relationships, and reports sheet names, populated-cell counts, and formula counts. Repeated `--contains TEXT` arguments check string cells and sheet names, and `--count N` checks sheet count. `--contains` excludes numeric cells and does not validate formula results; verify those separately with openpyxl. The checker does not calculate formulas or judge workbook appearance. Compare relevant values, types, formulas, styles, and totals with the task's source data.\n\nIf the Python checker cannot run, use an already configured environment to check the ZIP/XML package and internal relationships. Report the missing environment if those checks cannot run; do not claim structural validation.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless tLine truncated
|
||||
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_skill_xlsx"},"toolCallId":"call_skill_xlsx","content":[{"type":"text","text":"<skill_content name=\"office-xlsx\">\n<skill_resources>\nBase directory for this skill: {{cwd}}/office-skills/office-xlsx\nResolve relative paths mentioned by this skill against the base directory before using them. Load referenced resources only as needed.\n</skill_resources>\n\n<skill_instructions>\n# Excel workbooks\n\nFollow an explicit user or applicable AGENTS.md requirement for an environment or library. Otherwise call `load_workspace_dependencies` and run its Python executable with bundled `openpyxl` and `pandas`. Do not install packages or search for a system Python for the default workflow. If the tool is unavailable, use an already configured environment and report a missing dependency only when it prevents the requested operation.\n\nKeep scripts, working files, and outputs in the task workspace. The runtime and skill directory are shared read-only resources. Save to a new workbook unless the user requests an in-place edit.\n\n## Read and modify\n\nUse `openpyxl` for existing XLSX workbooks and targeted cell or style changes. Load with `data_only=False` when formulas must survive. Inspect sheet names, the affected cell types, formulas, styles, merged ranges, and referenced ranges before editing. Check the saved file by reopening it, including unchanged content that the request requires preserving.\n\nUse pandas for data analysis and transformations. A DataFrame is not the workbook: exporting it over an existing file can lose sheets, formulas, charts, and formatting. Write analysis results back to the intended ranges with openpyxl. `XlsxWriter` can create new workbooks, but cannot read or modify existing ones.\n\nFor a new workbook, the selected Python environment can write editable values, styles, and formulas directly:\n\n```python\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\n\nworkbook = Workbook()\nsheet = workbook.active\nsheet.title = \"Revenue\"\nfor row in [(\"Quarter\", \"Revenue\"), (\"Q1\", 12), (\"Q2\", 18), (\"Total\", \"=SUM(B2:B3)\")]:\n sheet.append(row)\nfor cell in sheet[1]:\n cell.font = Font(bold=True)\nsheet.column_dimensions[\"A\"].width = 18\nsheet.column_dimensions[\"B\"].width = 18\nworkbook.save(\"report.xlsx\")\n```\n\nPreserve numbers, dates, booleans, and identifiers as the intended cell types; formatting is not a type conversion. For modifications, load the existing file with `openpyxl.load_workbook(\"input.xlsx\", data_only=False)`, change the requested ranges, and save a separate result. Avoid a DataFrame round trip when workbook features must survive.\n\nWriting a formula does not calculate its result. openpyxl and XlsxWriter do not evaluate formulas; `data_only=True` returns cached values that may be absent or stale. When calculated results must be refreshed, load `office-recalculate`. Do not replace requested formulas with constants or report stale values as newly calculated results.\n\nDo not rename `.xls`, `.xlsb`, encrypted files, or macro-enabled files to `.xlsx`. They need an appropriate supported operation. `keep_vba=True` can preserve VBA package content in an XLSM workflow, but does not execute or edit macros and does not guarantee every advanced workbook feature survives. Preserve the original and verify such requirements explicitly.\n\n## Check and deliver\n\nReopen the saved workbook with openpyxl and verify the requested sheet names, values, types, formulas, styles, and totals against the source data, including unchanged content that must be preserved. These checks do not calculate formulas or judge workbook appearance.\n\nLoad `office-render` for requested images or visual inspection and whenever the user's primary task targets appearance, including cell fill colors, text alignment, spacing, or sizing. These appearance changes require rendering even without a separate visual-check request, unless the user explicitly skips it. New workbooks and data or formula edits do not require rendering solely because they include incidental basic formatting. In particular, bold headers and number formats accompanying data edits do not require loading `office-render` or running its commands.\n\nLoad `office-recalculate` when refreshed calculated values are needed and `office-export-pdf` for PDF output. Deliver after the requested data checks pass and the required operations finish.\n\nCall `present({\"files\":[{\"path\":\"report.xlsx\"}]})` with the actual final workbook path. It exposes the current source file without copying or preserving its bytes, so keep that file in place and omit intermediate scripts and reports unless requested. If `present` is unavailable, use the session's supported file delivery method.\n</skill_instructions>\n</skill_content>"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[17],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":1,"step":1}}
|
||||
{"type":"step/start","data":{"turn":1,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The skill is loaded."},{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":180,"outputTokens":10,"cacheReadTokens":0,"reasoningTokens":4},"stream":[{"type":"chunk","time":1791559903840,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791559903840,"index":0,"dt":[],"texts":["The skill is loaded."]},{"type":"chunk","time":1791559903840,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791559903840,"index":1,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1791559903840,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The skill is loaded."}}},{"type":"chunk","time":1791559903840,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1791559903840,"chunk":{"type":"usage","usage":{"inputTokens":180,"outputTokens":10,"cacheReadTokens":0,"reasoningTokens":4}}},{"type":"chunk","time":1791559903840,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}
|
||||
|
||||
Reference in new issue
Block a user