stata-code 0.3.1__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stata_code-0.3.1 → stata_code-0.4.0}/.gitignore +1 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/CHANGELOG.md +61 -1
- {stata_code-0.3.1 → stata_code-0.4.0}/PKG-INFO +37 -11
- {stata_code-0.3.1 → stata_code-0.4.0}/README.md +36 -10
- {stata_code-0.3.1 → stata_code-0.4.0}/SCHEMA.md +40 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/pyproject.toml +1 -1
- {stata_code-0.3.1 → stata_code-0.4.0}/schema/run_result.schema.json +126 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/__init__.py +3 -1
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/__init__.py +2 -0
- stata_code-0.4.0/stata_code/core/log_artifacts.py +431 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/runner.py +145 -4
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/schema.py +19 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/mcp/server.py +57 -1
- stata_code-0.4.0/tests/test_log_artifacts.py +154 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_mcp.py +5 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/LICENSE +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/LICENSE-POLICY.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/PUBLISHING.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/docs/design/hard_timeout.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/examples/01-basic-regression.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/examples/02-did-card-krueger.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/examples/03-graphs.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/examples/04-multi-session.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/examples/05-large-matrix.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/examples/README.md +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/scripts/export_schema.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/_pool.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/_refs.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/_runtime.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/core/errors.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/kernel/__init__.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/kernel/__main__.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/kernel/kernel.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/mcp/__init__.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/stata_code/mcp/__main__.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/__init__.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/fixtures/.gitkeep +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_cancel.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_errors.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_kernel.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_pool.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_runner.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_schema.py +0 -0
- {stata_code-0.3.1 → stata_code-0.4.0}/tests/test_schema_artifact.py +0 -0
|
@@ -4,7 +4,67 @@ All notable changes to `stata-code` are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project adheres
|
|
5
5
|
to semver-major.minor for the result schema (see `SCHEMA.md` §6).
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [0.4.0] — 2026-05-07
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Persistent per-run log bundles.** When a `.do` file path is supplied as
|
|
12
|
+
`origin_path`, the runner writes an immutable `log-files/<run>/` directory
|
|
13
|
+
next to the source file containing:
|
|
14
|
+
- `<run>.log` and `<run>.smcl` — Stata's textual and SMCL logs
|
|
15
|
+
- `manifest.json` — run metadata (elapsed_ms, rc, session, Stata edition)
|
|
16
|
+
- `submitted.do` — a snapshot of the code that was executed
|
|
17
|
+
- `graphs/` — captured graph files materialized from graph refs
|
|
18
|
+
- `outputs/` — newly created or modified table/export files copied from
|
|
19
|
+
the run's working directory
|
|
20
|
+
|
|
21
|
+
The directory name encodes UTC timestamp, session, and request IDs so
|
|
22
|
+
parallel runs and reruns are never ambiguous.
|
|
23
|
+
|
|
24
|
+
- **Working-directory defaults from `origin_path`.** Before running,
|
|
25
|
+
Stata `cd`s to the `.do` file's parent so relative `graph export`,
|
|
26
|
+
`putexcel`, `esttab using`, `collect export`, etc. output next to the
|
|
27
|
+
source. Toggle with `use_origin_workdir` / `useDoFileDirectory` setting.
|
|
28
|
+
Explicit `working_dir` overrides this.
|
|
29
|
+
|
|
30
|
+
- **Schema extensions.** `LogInfo.files` (`LogFileInfo`) carries the
|
|
31
|
+
bundle paths and derived `graphs_dir`/`outputs_dir`; `GraphInfo.file_path`
|
|
32
|
+
records where a graph was materialized; two new capabilities
|
|
33
|
+
`log_files` and `run_artifacts` signal support.
|
|
34
|
+
|
|
35
|
+
- **MCP tool options.** `stata_run` gains `persist_log_files`,
|
|
36
|
+
`persist_generated_files`, `origin_path`, `origin_kind`,
|
|
37
|
+
`origin_label`, `use_origin_workdir`, `working_dir`.
|
|
38
|
+
|
|
39
|
+
- **VS Code settings.** Three new configuration options:
|
|
40
|
+
`stataCode.persistLogFiles` (default `true`),
|
|
41
|
+
`stataCode.persistGeneratedFiles` (default `true`),
|
|
42
|
+
`stataCode.useDoFileDirectory` (default `true`).
|
|
43
|
+
|
|
44
|
+
- **VS Code tree views.** The Last Result tree now shows "saved" and
|
|
45
|
+
"N outputs" badges on the log node when artifacts are present; the
|
|
46
|
+
output log header prints `working_dir:`, `log_file:`, `smcl_file:`,
|
|
47
|
+
`graphs_dir:`, `outputs_dir:` for each run.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **VSCode MCP startup.** The extension now expands common macOS Python
|
|
52
|
+
script directories before spawning `stata-code-mcp`, tries workspace
|
|
53
|
+
`.venv` and `python -m stata_code.mcp` fallbacks for the default command,
|
|
54
|
+
and writes child-process stderr to the `stata-code` output channel so
|
|
55
|
+
missing PATH / missing dependency failures are actionable.
|
|
56
|
+
- **VSCode toolbar ordering.** Run-all and run-selection now share the same
|
|
57
|
+
ordinary `editor/title` toolbar sequence, with ordering moved later in the
|
|
58
|
+
`navigation` group to reduce interleaving from other extensions.
|
|
59
|
+
|
|
60
|
+
## [0.3.2] — 2026-05-08
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- **VSCode toolbar ordering.** Editor title-bar actions now live in one
|
|
65
|
+
contiguous `navigation` group so `stata-code` buttons stay together. The
|
|
66
|
+
order prioritizes run commands first, then data/output views, session
|
|
67
|
+
controls, cancellation/reset, and working-directory actions.
|
|
8
68
|
|
|
9
69
|
## [0.3.1] — 2026-05-07
|
|
10
70
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stata-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Agent-native Stata bridge — one core, multiple frontends (MCP, Jupyter, VSCode)
|
|
5
5
|
Project-URL: Homepage, https://github.com/brycewang-stanford/stata-code
|
|
6
6
|
Project-URL: Repository, https://github.com/brycewang-stanford/stata-code
|
|
@@ -135,7 +135,7 @@ else:
|
|
|
135
135
|
|
|
136
136
|
### As an MCP Server
|
|
137
137
|
|
|
138
|
-
After `pip install stata-code`, the `stata-code-mcp` binary is on your `PATH`. You can wire it into Claude Code, Cursor, Claude Desktop, or any other MCP-compatible client.
|
|
138
|
+
After `pip install "stata-code[mcp]"`, the `stata-code-mcp` binary is on your `PATH`. You can wire it into Claude Code, Cursor, Claude Desktop, or any other MCP-compatible client.
|
|
139
139
|
|
|
140
140
|
#### Claude Code via `claude mcp add` (recommended)
|
|
141
141
|
|
|
@@ -201,17 +201,30 @@ The MCP server registers 8 tools:
|
|
|
201
201
|
|
|
202
202
|
### As a Jupyter Kernel
|
|
203
203
|
|
|
204
|
+
`stata-code` ships a Jupyter kernel as part of the Python package — there is no separate "Jupyter plugin" in the JupyterLab extension marketplace. Installation is two steps: `pip install` the package with the `kernel` extra, then register the kernelspec with Jupyter.
|
|
205
|
+
|
|
206
|
+
**Prerequisites**: Stata 17+ installed locally with a valid license (the kernel calls Stata via `pystata`), and Python 3.10+ with `jupyter`/`jupyterlab` already on the same environment.
|
|
207
|
+
|
|
204
208
|
```bash
|
|
209
|
+
# 1. Install stata-code with the kernel extra (pulls in ipykernel)
|
|
210
|
+
pip install "stata-code[kernel]"
|
|
211
|
+
|
|
212
|
+
# 2. Register the kernelspec into Jupyter's user data dir
|
|
205
213
|
stata-code-kernel install --user
|
|
214
|
+
# Or, equivalently:
|
|
215
|
+
# python -m stata_code.kernel install --user
|
|
206
216
|
```
|
|
207
217
|
|
|
208
|
-
|
|
218
|
+
Verify the kernel is registered:
|
|
209
219
|
|
|
210
220
|
```bash
|
|
211
|
-
|
|
221
|
+
jupyter kernelspec list
|
|
222
|
+
# should include an entry named `stata`
|
|
212
223
|
```
|
|
213
224
|
|
|
214
|
-
Then open a
|
|
225
|
+
Then open Jupyter Notebook / JupyterLab (or a `.ipynb` in VS Code), pick **Stata** in the kernel selector, and run Stata commands in cells. Logs, graphs, and warnings render inline.
|
|
226
|
+
|
|
227
|
+
> JupyterLab's Extension Manager only installs front-end JS extensions, so it cannot install a kernel — `pip install` plus the `install --user` step above is the only supported path.
|
|
215
228
|
|
|
216
229
|
### As a VS Code Extension
|
|
217
230
|
|
|
@@ -224,7 +237,7 @@ code --install-extension brycewang-stanford.stata-code-vscode
|
|
|
224
237
|
|
|
225
238
|
Or open the **Extensions** sidebar in VS Code and search `stata-code`.
|
|
226
239
|
|
|
227
|
-
The extension still requires
|
|
240
|
+
The extension still requires the MCP extra on your system Python (`pip install "stata-code[mcp]"`), so that `stata-code-mcp` resolves on `PATH` and can import the MCP SDK. Stata 17+ and a valid Stata license are required as for any other frontend.
|
|
228
241
|
|
|
229
242
|
---
|
|
230
243
|
|
|
@@ -464,7 +477,7 @@ else:
|
|
|
464
477
|
|
|
465
478
|
### 作为 MCP server
|
|
466
479
|
|
|
467
|
-
`pip install stata-code` 之后,`stata-code-mcp` 会出现在你的 `PATH` 中。可以接到 Claude Code、Cursor、Claude Desktop 等任何兼容 MCP 的客户端里。
|
|
480
|
+
`pip install "stata-code[mcp]"` 之后,`stata-code-mcp` 会出现在你的 `PATH` 中。可以接到 Claude Code、Cursor、Claude Desktop 等任何兼容 MCP 的客户端里。
|
|
468
481
|
|
|
469
482
|
#### 用 `claude mcp add` 接入 Claude Code(推荐)
|
|
470
483
|
|
|
@@ -530,17 +543,30 @@ MCP server 注册了 8 个工具:
|
|
|
530
543
|
|
|
531
544
|
### 作为 Jupyter kernel
|
|
532
545
|
|
|
546
|
+
`stata-code` 的 Jupyter 支持是以 **kernel** 形式打包在 Python 包里的 —— JupyterLab 插件市场里**没有**独立的 "stata-code 插件"。安装分两步:先 `pip install` 安装带 `kernel` extra 的包,再把 kernelspec 注册到 Jupyter。
|
|
547
|
+
|
|
548
|
+
**前置条件**:本机已经安装 Stata 17+ 且持有合法许可证(kernel 通过 `pystata` 调用本地 Stata),同一个 Python 环境里已经装好 `jupyter`/`jupyterlab`,Python 版本 ≥ 3.10。
|
|
549
|
+
|
|
533
550
|
```bash
|
|
551
|
+
# 1. 安装带 kernel extra 的 stata-code(会同时装上 ipykernel)
|
|
552
|
+
pip install "stata-code[kernel]"
|
|
553
|
+
|
|
554
|
+
# 2. 把 kernelspec 注册到当前用户的 Jupyter data dir
|
|
534
555
|
stata-code-kernel install --user
|
|
556
|
+
# 等价命令:
|
|
557
|
+
# python -m stata_code.kernel install --user
|
|
535
558
|
```
|
|
536
559
|
|
|
537
|
-
|
|
560
|
+
检查 kernel 是否注册成功:
|
|
538
561
|
|
|
539
562
|
```bash
|
|
540
|
-
|
|
563
|
+
jupyter kernelspec list
|
|
564
|
+
# 输出里应该能看到名为 `stata` 的条目
|
|
541
565
|
```
|
|
542
566
|
|
|
543
|
-
然后打开
|
|
567
|
+
然后打开 Jupyter Notebook / JupyterLab(或 VS Code 中的 `.ipynb`),在 kernel 选择器里挑 **Stata**,cell 里直接写 Stata 命令即可,日志、graphs 和 warnings 会以内联方式显示。
|
|
568
|
+
|
|
569
|
+
> JupyterLab 的 Extension Manager 只能安装前端 JS 扩展,**装不了 kernel**。所以上面的 `pip install` + `install --user` 是唯一支持的安装路径。
|
|
544
570
|
|
|
545
571
|
### 作为 VS Code 扩展
|
|
546
572
|
|
|
@@ -553,7 +579,7 @@ code --install-extension brycewang-stanford.stata-code-vscode
|
|
|
553
579
|
|
|
554
580
|
或者打开 VS Code 的 **Extensions** 侧栏,搜索 `stata-code`。
|
|
555
581
|
|
|
556
|
-
扩展仍然依赖系统 Python
|
|
582
|
+
扩展仍然依赖系统 Python 上安装了 MCP extra(`pip install "stata-code[mcp]"`),从而保证 `stata-code-mcp` 在 `PATH` 上可用,并且能导入 MCP SDK。和其它前端一样,需要 Stata 17+ 和有效的 Stata 许可证。
|
|
557
583
|
|
|
558
584
|
---
|
|
559
585
|
|
|
@@ -97,7 +97,7 @@ else:
|
|
|
97
97
|
|
|
98
98
|
### As an MCP Server
|
|
99
99
|
|
|
100
|
-
After `pip install stata-code`, the `stata-code-mcp` binary is on your `PATH`. You can wire it into Claude Code, Cursor, Claude Desktop, or any other MCP-compatible client.
|
|
100
|
+
After `pip install "stata-code[mcp]"`, the `stata-code-mcp` binary is on your `PATH`. You can wire it into Claude Code, Cursor, Claude Desktop, or any other MCP-compatible client.
|
|
101
101
|
|
|
102
102
|
#### Claude Code via `claude mcp add` (recommended)
|
|
103
103
|
|
|
@@ -163,17 +163,30 @@ The MCP server registers 8 tools:
|
|
|
163
163
|
|
|
164
164
|
### As a Jupyter Kernel
|
|
165
165
|
|
|
166
|
+
`stata-code` ships a Jupyter kernel as part of the Python package — there is no separate "Jupyter plugin" in the JupyterLab extension marketplace. Installation is two steps: `pip install` the package with the `kernel` extra, then register the kernelspec with Jupyter.
|
|
167
|
+
|
|
168
|
+
**Prerequisites**: Stata 17+ installed locally with a valid license (the kernel calls Stata via `pystata`), and Python 3.10+ with `jupyter`/`jupyterlab` already on the same environment.
|
|
169
|
+
|
|
166
170
|
```bash
|
|
171
|
+
# 1. Install stata-code with the kernel extra (pulls in ipykernel)
|
|
172
|
+
pip install "stata-code[kernel]"
|
|
173
|
+
|
|
174
|
+
# 2. Register the kernelspec into Jupyter's user data dir
|
|
167
175
|
stata-code-kernel install --user
|
|
176
|
+
# Or, equivalently:
|
|
177
|
+
# python -m stata_code.kernel install --user
|
|
168
178
|
```
|
|
169
179
|
|
|
170
|
-
|
|
180
|
+
Verify the kernel is registered:
|
|
171
181
|
|
|
172
182
|
```bash
|
|
173
|
-
|
|
183
|
+
jupyter kernelspec list
|
|
184
|
+
# should include an entry named `stata`
|
|
174
185
|
```
|
|
175
186
|
|
|
176
|
-
Then open a
|
|
187
|
+
Then open Jupyter Notebook / JupyterLab (or a `.ipynb` in VS Code), pick **Stata** in the kernel selector, and run Stata commands in cells. Logs, graphs, and warnings render inline.
|
|
188
|
+
|
|
189
|
+
> JupyterLab's Extension Manager only installs front-end JS extensions, so it cannot install a kernel — `pip install` plus the `install --user` step above is the only supported path.
|
|
177
190
|
|
|
178
191
|
### As a VS Code Extension
|
|
179
192
|
|
|
@@ -186,7 +199,7 @@ code --install-extension brycewang-stanford.stata-code-vscode
|
|
|
186
199
|
|
|
187
200
|
Or open the **Extensions** sidebar in VS Code and search `stata-code`.
|
|
188
201
|
|
|
189
|
-
The extension still requires
|
|
202
|
+
The extension still requires the MCP extra on your system Python (`pip install "stata-code[mcp]"`), so that `stata-code-mcp` resolves on `PATH` and can import the MCP SDK. Stata 17+ and a valid Stata license are required as for any other frontend.
|
|
190
203
|
|
|
191
204
|
---
|
|
192
205
|
|
|
@@ -426,7 +439,7 @@ else:
|
|
|
426
439
|
|
|
427
440
|
### 作为 MCP server
|
|
428
441
|
|
|
429
|
-
`pip install stata-code` 之后,`stata-code-mcp` 会出现在你的 `PATH` 中。可以接到 Claude Code、Cursor、Claude Desktop 等任何兼容 MCP 的客户端里。
|
|
442
|
+
`pip install "stata-code[mcp]"` 之后,`stata-code-mcp` 会出现在你的 `PATH` 中。可以接到 Claude Code、Cursor、Claude Desktop 等任何兼容 MCP 的客户端里。
|
|
430
443
|
|
|
431
444
|
#### 用 `claude mcp add` 接入 Claude Code(推荐)
|
|
432
445
|
|
|
@@ -492,17 +505,30 @@ MCP server 注册了 8 个工具:
|
|
|
492
505
|
|
|
493
506
|
### 作为 Jupyter kernel
|
|
494
507
|
|
|
508
|
+
`stata-code` 的 Jupyter 支持是以 **kernel** 形式打包在 Python 包里的 —— JupyterLab 插件市场里**没有**独立的 "stata-code 插件"。安装分两步:先 `pip install` 安装带 `kernel` extra 的包,再把 kernelspec 注册到 Jupyter。
|
|
509
|
+
|
|
510
|
+
**前置条件**:本机已经安装 Stata 17+ 且持有合法许可证(kernel 通过 `pystata` 调用本地 Stata),同一个 Python 环境里已经装好 `jupyter`/`jupyterlab`,Python 版本 ≥ 3.10。
|
|
511
|
+
|
|
495
512
|
```bash
|
|
513
|
+
# 1. 安装带 kernel extra 的 stata-code(会同时装上 ipykernel)
|
|
514
|
+
pip install "stata-code[kernel]"
|
|
515
|
+
|
|
516
|
+
# 2. 把 kernelspec 注册到当前用户的 Jupyter data dir
|
|
496
517
|
stata-code-kernel install --user
|
|
518
|
+
# 等价命令:
|
|
519
|
+
# python -m stata_code.kernel install --user
|
|
497
520
|
```
|
|
498
521
|
|
|
499
|
-
|
|
522
|
+
检查 kernel 是否注册成功:
|
|
500
523
|
|
|
501
524
|
```bash
|
|
502
|
-
|
|
525
|
+
jupyter kernelspec list
|
|
526
|
+
# 输出里应该能看到名为 `stata` 的条目
|
|
503
527
|
```
|
|
504
528
|
|
|
505
|
-
然后打开
|
|
529
|
+
然后打开 Jupyter Notebook / JupyterLab(或 VS Code 中的 `.ipynb`),在 kernel 选择器里挑 **Stata**,cell 里直接写 Stata 命令即可,日志、graphs 和 warnings 会以内联方式显示。
|
|
530
|
+
|
|
531
|
+
> JupyterLab 的 Extension Manager 只能安装前端 JS 扩展,**装不了 kernel**。所以上面的 `pip install` + `install --user` 是唯一支持的安装路径。
|
|
506
532
|
|
|
507
533
|
### 作为 VS Code 扩展
|
|
508
534
|
|
|
@@ -515,7 +541,7 @@ code --install-extension brycewang-stanford.stata-code-vscode
|
|
|
515
541
|
|
|
516
542
|
或者打开 VS Code 的 **Extensions** 侧栏,搜索 `stata-code`。
|
|
517
543
|
|
|
518
|
-
扩展仍然依赖系统 Python
|
|
544
|
+
扩展仍然依赖系统 Python 上安装了 MCP extra(`pip install "stata-code[mcp]"`),从而保证 `stata-code-mcp` 在 `PATH` 上可用,并且能导入 MCP SDK。和其它前端一样,需要 Stata 17+ 和有效的 Stata 许可证。
|
|
519
545
|
|
|
520
546
|
---
|
|
521
547
|
|
|
@@ -228,6 +228,7 @@ The single biggest token-economy decision in the schema. Default response carrie
|
|
|
228
228
|
| `complete` | `bool` | Reserved for v2 streaming. Always `true` in v1. v2 may emit interim results with `complete: false`. |
|
|
229
229
|
| `error_window` | `string \| null` | When `error` is non-null, the ~10 log lines immediately surrounding the failing emission (regardless of `head`/`tail` window). Cheap for the producer to compute; saves agents from bumping `log_lines` or fetching the full log just to see "what did Stata say right when it broke." `null` on success or when not computable. |
|
|
230
230
|
| `ref` | `string \| null` | Opaque reference for `get_log`. Required when `truncated: true`; may be set when `truncated: false` for caller convenience; `null` is allowed when full log is in `head`. |
|
|
231
|
+
| `files` | `object \| null` | Persistent `.log` / `.smcl` artifacts written for file-backed runs when requested. `null` when no files were written. See "Persistent log files" below. |
|
|
231
232
|
|
|
232
233
|
**ANSI handling.** All log views (`head`, `tail`, `error_window`, the payload returned by `get_log(ref)`) are ANSI-escape-stripped, consistently.
|
|
233
234
|
|
|
@@ -237,6 +238,37 @@ The single biggest token-economy decision in the schema. Default response carrie
|
|
|
237
238
|
|
|
238
239
|
**Defaults.** `head=20`, `tail=20`. Configurable per call via `log_lines_head` / `log_lines_tail` (see §4). If `lines_total ≤ head+tail`, the producer MUST set `truncated: false`, place the full log in `head`, set `tail: ""`, and set `ref: null`.
|
|
239
240
|
|
|
241
|
+
**Persistent log files.** When a frontend passes a source `.do` path and requests `persist_log_files`, producers write immutable run artifacts under:
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
<do-file-dir>/log-files/<do-stem>__<UTC timestamp>__<session_id>__<request_id>/
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`log.files` then has:
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"directory": "/abs/path/log-files/test1__20260508T012233123Z__main__abc123",
|
|
252
|
+
"log_path": "/abs/path/.../test1__20260508T012233123Z__main__abc123.log",
|
|
253
|
+
"smcl_path": "/abs/path/.../test1__20260508T012233123Z__main__abc123.smcl",
|
|
254
|
+
"manifest_path": "/abs/path/.../manifest.json",
|
|
255
|
+
"code_path": "/abs/path/.../submitted.do",
|
|
256
|
+
"working_dir": "/abs/path",
|
|
257
|
+
"graphs_dir": "/abs/path/.../graphs",
|
|
258
|
+
"outputs_dir": "/abs/path/.../outputs",
|
|
259
|
+
"graph_paths": ["/abs/path/.../graphs/01-Graph.png"],
|
|
260
|
+
"output_paths": ["/abs/path/.../outputs/table.xlsx"],
|
|
261
|
+
"policy": "per_run_directory",
|
|
262
|
+
"append": false
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The stable folder name is `log-files`; timestamps belong on child run directories, not on the root. Producers SHOULD NOT append different executions into one log file, because parallel sessions, reruns after a pause, and selection/cell executions become ambiguous. Each run directory SHOULD include a manifest and submitted-code snapshot so the log is attributable without relying on editor history.
|
|
267
|
+
|
|
268
|
+
When `origin_path` is supplied, producers SHOULD default Stata's working directory to the source `.do` file's directory before running. This mirrors how users organize project-relative `graph export`, `putexcel`, `esttab using`, `collect export`, and similar output commands. Frontends may disable this with `use_origin_workdir: false` or override it with `working_dir`.
|
|
269
|
+
|
|
270
|
+
When `persist_generated_files` is true, producers SHOULD copy newly created or modified common output files from the run working directory into `outputs/`, preserving relative paths where practical. Captured graph refs SHOULD also be materialized into `graphs/`, with the corresponding `GraphInfo.file_path` set.
|
|
271
|
+
|
|
240
272
|
### 3.4 `results`
|
|
241
273
|
|
|
242
274
|
Stata's `r()` and `e()` return dictionaries, structurally separated. Each follows the same shape:
|
|
@@ -317,6 +349,7 @@ Each entry describes one captured graph. By default the bytes are **not** inline
|
|
|
317
349
|
| `source_command` | `string \| null` | The user-submitted command line that produced this graph, when isolatable. |
|
|
318
350
|
| `source_line` | `int \| null` | 1-indexed line within the submitted code that produced this graph. |
|
|
319
351
|
| `inline` | `string \| null` | Base64-encoded bytes when the caller explicitly asked for inline (`include_graphs: "inline"`); else `null`. |
|
|
352
|
+
| `file_path` | `string \| null` | Persistent graph file path when the run bundle materialized captured graphs under `log.files.graphs_dir`; else `null`. |
|
|
320
353
|
|
|
321
354
|
### 3.7 `error`
|
|
322
355
|
|
|
@@ -426,6 +459,11 @@ The schema also dictates what callers may *ask for*. Every frontend exposes the
|
|
|
426
459
|
| `graph_format` | `"png" \| "svg" \| "pdf"` | `"png"` | Render format. |
|
|
427
460
|
| `include_dataset_variables` | `bool` | `true` | Set `false` to omit `dataset.variables`. |
|
|
428
461
|
| `timeout_ms` | `int \| null` | `600000` (10 min) | Hard timeout. `null` disables. On expiry, returns `ok: false`, `error.kind: "timeout"`, `rc: -2`. Frontends MAY override the default if their use case demands. |
|
|
462
|
+
| `persist_log_files` | `bool` | `false` | With `origin_path`, writes immutable `.log` / `.smcl` / manifest files under the source `.do` file's `log-files/` directory. |
|
|
463
|
+
| `persist_generated_files` | `bool` | `true` | When log files are persisted, also copies newly created or modified table/export files into `outputs/` and captured graphs into `graphs/`. |
|
|
464
|
+
| `origin_path` | `string \| null` | `null` | Absolute source `.do` path used for working-directory defaults and run-bundle placement. |
|
|
465
|
+
| `use_origin_workdir` | `bool` | `true` | With `origin_path`, `cd` Stata to the source `.do` directory before running. |
|
|
466
|
+
| `working_dir` | `string \| null` | `null` | Explicit Stata working directory; overrides the source `.do` directory. |
|
|
429
467
|
|
|
430
468
|
Frontends translate their native idiom (MCP `inputSchema`, Jupyter kernel options, VSCode commands) into these names without renaming.
|
|
431
469
|
|
|
@@ -481,6 +519,8 @@ These are *additions* to `run()`. A minimal client only needs `run()` plus which
|
|
|
481
519
|
| `matrix_ref` | Producer can emit large matrices as refs and supports `get_matrix`. |
|
|
482
520
|
| `multi_session` | Producer supports `session_id != "main"` and `list_sessions`. |
|
|
483
521
|
| `inline_graphs` | Producer supports `include_graphs: "inline"`. |
|
|
522
|
+
| `log_files` | Producer can persist immutable per-run `.log` / `.smcl` bundles. |
|
|
523
|
+
| `run_artifacts` | Producer can materialize captured graphs and copied table/export outputs into the run bundle. |
|
|
484
524
|
|
|
485
525
|
Consumers detect optional features via `capabilities`, not by parsing `schema_version`. Producers may add entries; agents MUST treat unknown capability names as opaque.
|
|
486
526
|
|
|
@@ -247,6 +247,18 @@
|
|
|
247
247
|
"GraphInfo": {
|
|
248
248
|
"additionalProperties": true,
|
|
249
249
|
"properties": {
|
|
250
|
+
"file_path": {
|
|
251
|
+
"anyOf": [
|
|
252
|
+
{
|
|
253
|
+
"type": "string"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"type": "null"
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
"default": null,
|
|
260
|
+
"title": "File Path"
|
|
261
|
+
},
|
|
250
262
|
"format": {
|
|
251
263
|
"$ref": "#/$defs/GraphFormat",
|
|
252
264
|
"default": "png"
|
|
@@ -327,6 +339,109 @@
|
|
|
327
339
|
"title": "GraphInfo",
|
|
328
340
|
"type": "object"
|
|
329
341
|
},
|
|
342
|
+
"LogFileInfo": {
|
|
343
|
+
"additionalProperties": true,
|
|
344
|
+
"description": "Persistent on-disk artifacts written for file-backed runs.",
|
|
345
|
+
"properties": {
|
|
346
|
+
"append": {
|
|
347
|
+
"default": false,
|
|
348
|
+
"title": "Append",
|
|
349
|
+
"type": "boolean"
|
|
350
|
+
},
|
|
351
|
+
"code_path": {
|
|
352
|
+
"anyOf": [
|
|
353
|
+
{
|
|
354
|
+
"type": "string"
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"type": "null"
|
|
358
|
+
}
|
|
359
|
+
],
|
|
360
|
+
"default": null,
|
|
361
|
+
"title": "Code Path"
|
|
362
|
+
},
|
|
363
|
+
"directory": {
|
|
364
|
+
"title": "Directory",
|
|
365
|
+
"type": "string"
|
|
366
|
+
},
|
|
367
|
+
"graph_paths": {
|
|
368
|
+
"items": {
|
|
369
|
+
"type": "string"
|
|
370
|
+
},
|
|
371
|
+
"title": "Graph Paths",
|
|
372
|
+
"type": "array"
|
|
373
|
+
},
|
|
374
|
+
"graphs_dir": {
|
|
375
|
+
"anyOf": [
|
|
376
|
+
{
|
|
377
|
+
"type": "string"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"type": "null"
|
|
381
|
+
}
|
|
382
|
+
],
|
|
383
|
+
"default": null,
|
|
384
|
+
"title": "Graphs Dir"
|
|
385
|
+
},
|
|
386
|
+
"log_path": {
|
|
387
|
+
"title": "Log Path",
|
|
388
|
+
"type": "string"
|
|
389
|
+
},
|
|
390
|
+
"manifest_path": {
|
|
391
|
+
"title": "Manifest Path",
|
|
392
|
+
"type": "string"
|
|
393
|
+
},
|
|
394
|
+
"output_paths": {
|
|
395
|
+
"items": {
|
|
396
|
+
"type": "string"
|
|
397
|
+
},
|
|
398
|
+
"title": "Output Paths",
|
|
399
|
+
"type": "array"
|
|
400
|
+
},
|
|
401
|
+
"outputs_dir": {
|
|
402
|
+
"anyOf": [
|
|
403
|
+
{
|
|
404
|
+
"type": "string"
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"type": "null"
|
|
408
|
+
}
|
|
409
|
+
],
|
|
410
|
+
"default": null,
|
|
411
|
+
"title": "Outputs Dir"
|
|
412
|
+
},
|
|
413
|
+
"policy": {
|
|
414
|
+
"const": "per_run_directory",
|
|
415
|
+
"default": "per_run_directory",
|
|
416
|
+
"title": "Policy",
|
|
417
|
+
"type": "string"
|
|
418
|
+
},
|
|
419
|
+
"smcl_path": {
|
|
420
|
+
"title": "Smcl Path",
|
|
421
|
+
"type": "string"
|
|
422
|
+
},
|
|
423
|
+
"working_dir": {
|
|
424
|
+
"anyOf": [
|
|
425
|
+
{
|
|
426
|
+
"type": "string"
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
"type": "null"
|
|
430
|
+
}
|
|
431
|
+
],
|
|
432
|
+
"default": null,
|
|
433
|
+
"title": "Working Dir"
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
"required": [
|
|
437
|
+
"directory",
|
|
438
|
+
"log_path",
|
|
439
|
+
"smcl_path",
|
|
440
|
+
"manifest_path"
|
|
441
|
+
],
|
|
442
|
+
"title": "LogFileInfo",
|
|
443
|
+
"type": "object"
|
|
444
|
+
},
|
|
330
445
|
"LogInfo": {
|
|
331
446
|
"additionalProperties": true,
|
|
332
447
|
"properties": {
|
|
@@ -352,6 +467,17 @@
|
|
|
352
467
|
"default": null,
|
|
353
468
|
"title": "Error Window"
|
|
354
469
|
},
|
|
470
|
+
"files": {
|
|
471
|
+
"anyOf": [
|
|
472
|
+
{
|
|
473
|
+
"$ref": "#/$defs/LogFileInfo"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"type": "null"
|
|
477
|
+
}
|
|
478
|
+
],
|
|
479
|
+
"default": null
|
|
480
|
+
},
|
|
355
481
|
"head": {
|
|
356
482
|
"default": "",
|
|
357
483
|
"title": "Head",
|
|
@@ -42,6 +42,7 @@ from stata_code.core.schema import (
|
|
|
42
42
|
GraphFormat,
|
|
43
43
|
GraphInfo,
|
|
44
44
|
IncludeGraphs,
|
|
45
|
+
LogFileInfo,
|
|
45
46
|
LogInfo,
|
|
46
47
|
Matrix,
|
|
47
48
|
ResultsInfo,
|
|
@@ -57,7 +58,7 @@ from stata_code.core.schema import (
|
|
|
57
58
|
# Convenience alias: `run(...)` == `execute(...)`.
|
|
58
59
|
run = execute
|
|
59
60
|
|
|
60
|
-
__version__ = "0.
|
|
61
|
+
__version__ = "0.4.0"
|
|
61
62
|
|
|
62
63
|
__all__ = [
|
|
63
64
|
# Primary entry points
|
|
@@ -86,6 +87,7 @@ __all__ = [
|
|
|
86
87
|
"GraphInfo",
|
|
87
88
|
"IncludeGraphs",
|
|
88
89
|
"LogInfo",
|
|
90
|
+
"LogFileInfo",
|
|
89
91
|
"Matrix",
|
|
90
92
|
"ResultsInfo",
|
|
91
93
|
"StataEdition",
|
|
@@ -27,6 +27,7 @@ from stata_code.core.schema import (
|
|
|
27
27
|
GraphFormat,
|
|
28
28
|
GraphInfo,
|
|
29
29
|
IncludeGraphs,
|
|
30
|
+
LogFileInfo,
|
|
30
31
|
LogInfo,
|
|
31
32
|
Matrix,
|
|
32
33
|
ResultsInfo,
|
|
@@ -58,6 +59,7 @@ __all__ = [
|
|
|
58
59
|
"ErrorContext",
|
|
59
60
|
"Suggestion",
|
|
60
61
|
"LogInfo",
|
|
62
|
+
"LogFileInfo",
|
|
61
63
|
"ResultsInfo",
|
|
62
64
|
"StataReturns",
|
|
63
65
|
"Matrix",
|