@calcit/procs 0.12.51 → 0.12.53

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.
Files changed (28) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/README.md +1 -2
  3. package/RFCs/03-18-query-def-tree-show-chunked-display-plan.md +1 -1
  4. package/RFCs/07-06-semantic-tree-navigation-rfc.md +10 -10
  5. package/RFCs/07-26-agent-semantic-interface-roadmap-rfc.md +793 -0
  6. package/RFCs/README.md +2 -1
  7. package/editing-history/2026-02-23-2321-ns-imports-code-fixes.md +7 -7
  8. package/editing-history/2026-02-27-2200-split-def-command.md +3 -3
  9. package/editing-history/2026-02-27-2212-tree-raise-wrap.md +4 -4
  10. package/editing-history/2026-03-10-1040-edit-schema-primitive-tag-support.md +4 -4
  11. package/editing-history/2026-07-26-1220-to-js-data-options.md +14 -0
  12. package/editing-history/2026-07-26-1244-release-0.12.52.md +12 -0
  13. package/editing-history/2026-07-26-1313-cli-long-option-hints.md +14 -0
  14. package/editing-history/2026-07-26-1341-method-display-literals.md +5 -0
  15. package/editing-history/2026-07-26-2104-agent-semantic-interface-rfc.md +11 -0
  16. package/editing-history/2026-07-26-2107-static-analysis-agent-cli.md +30 -0
  17. package/editing-history/202607221613-remove-bundle-calcit-cli.md +7 -0
  18. package/editing-history/202607221944-replace-cr-sync-with-script.md +7 -0
  19. package/editing-history/20260728-1500-caps-module-status.md +17 -0
  20. package/editing-history/20260728-1501-release-0.12.53.md +6 -0
  21. package/editing-history/archived/2026-03-20-1229-query-window-3-with-parent-preview.md +5 -5
  22. package/editing-history/archived/2026-03-23-1137-command-echo-tool-output-cleanup.md +2 -2
  23. package/lib/calcit-data.d.mts +1 -1
  24. package/lib/calcit-data.mjs +39 -8
  25. package/lib/calcit.procs.d.mts +1 -0
  26. package/lib/package.json +3 -2
  27. package/package.json +3 -2
  28. package/ts-src/calcit-data.mts +40 -8
package/RFCs/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # RFC 整理索引
2
2
 
3
- 更新时间:2026-06-29
3
+ 更新时间:2026-07-26
4
4
 
5
5
  ## 目录原则
6
6
 
@@ -32,6 +32,7 @@
32
32
  | `07-06-semantic-tree-navigation-rfc.md` | Draft | 语义化树形导航与编辑:路径标注、多候选交互、锚点搜索替换、结构化查询语言。 |
33
33
  | `07-19-doc-knowledge-index-rfc.md` | Draft | Markdown/Calcit snapshot 的知识节点、关系索引与用户级增量缓存方案。 |
34
34
  | `07-19-type-introspection-consistency-rfc.md` | Implemented | 类型自省一致性改进:`&methods-of` 支持裸类型定义、`Enum` Display 补 variants、`to-pairs`/`keys` 类型签名修正(第 4 项可选新增 proc 延后)。 |
35
+ | `07-26-agent-semantic-interface-roadmap-rfc.md` | Draft | 面向 LLM Agent 的统一语义查询、静态类型发现、文档索引、结构化诊断、事务编辑和效率基准路线图。 |
35
36
 
36
37
  ## 已执行的清理
37
38
 
@@ -6,9 +6,9 @@
6
6
 
7
7
  ## 发现的 Bug
8
8
 
9
- ### Bug 1:`imports -e 'rule'` 产生平坦结构,与 `extract_require_rules` 不兼容
9
+ ### Bug 1:`imports --code 'rule'` 产生平坦结构,与 `extract_require_rules` 不兼容
10
10
 
11
- - **现象**:`imports -e 'respo.core :refer $ sym'` 成功,但之后执行 `add-import` 会丢失已有 imports
11
+ - **现象**:`imports --code 'respo.core :refer $ sym'` 成功,但之后执行 `add-import` 会丢失已有 imports
12
12
  - **根因**:`handle_imports` 手工拼接 `ns_code_items`(平坦 list),产生结构:
13
13
  ```
14
14
  ["ns", "my.ns", ":require", "respo.core", ":refer", "$", "sym"]
@@ -20,14 +20,14 @@
20
20
  导致后续任何依赖 `extract_require_rules` 的操作(`add-import`、`rm-import`)全部解析不到已有规则。
21
21
  - **修复**:重写 `handle_imports` 的 rules 解析逻辑,统一调用 `build_ns_code` 生成嵌套结构。同时自动区分输入是单条规则(flat array of strings)还是多条规则(array of arrays)。
22
22
 
23
- ### Bug 2:`imports -e ':require ...'` 静默产生 `:require :require` 重复
23
+ ### Bug 2:`imports --code ':require ...'` 静默产生 `:require :require` 重复
24
24
 
25
25
  - **现象**:写 `:require respo.core :refer $ sym` 不报错,但生成 `ns my.ns :require :require respo.core ...`
26
26
  - **修复**:当 Cirru 解析后发现数组第一元素为 `:require` 字符串,立即返回错误消息,引导用户不包含 `:require` 前缀。
27
27
 
28
- ### Bug 3:`add-ns -e 'ns WRONG_NAME ...'` 名称不一致静默通过
28
+ ### Bug 3:`add-ns --code 'ns WRONG_NAME ...'` 名称不一致静默通过
29
29
 
30
- - **现象**:`cr edit add-ns my.ns -e 'ns wrong.ns ...'` 成功,file-key 是 `my.ns`,但 ns 声明内写的是 `wrong.ns`,导致 `query ns my.ns` 看到内部名称错误
30
+ - **现象**:`cr edit add-ns my.ns --code 'ns wrong.ns ...'` 成功,file-key 是 `my.ns`,但 ns 声明内写的是 `wrong.ns`,导致 `query ns my.ns` 看到内部名称错误
31
31
  - **修复**:当输入解析为 `ns` 表达式时,校验第二个元素是否与位置参数一致,不一致则 Error。
32
32
 
33
33
  ## 修改文件
@@ -36,7 +36,7 @@
36
36
 
37
37
  ## 知识点
38
38
 
39
- - `imports` 命令的 `-e` 输入格式:**不含 `:require` 前缀**,直接是规则体(`src-ns :refer $ sym`)。单条规则传平坦字符串,多条规则用 `-f` 文件(每行一条)或 `-j` JSON 数组(元素为数组)。
39
+ - `imports` 命令的 `--code` 输入格式:**不含 `:require` 前缀**,直接是规则体(`src-ns :refer $ sym`)。单条规则用 `--code`,多条规则用 `--file`(每行一条)或通过 stdin JSON 数组(元素为数组)。
40
40
  - `add-import` 和 `imports` 的格式一致,都是 `src-ns :refer $ sym`(无 `:require` 前缀)。
41
- - `add-ns -e` 中若传完整 `ns` 表达式,内部名称必须与位置参数完全匹配。
41
+ - `add-ns --code` 中若传完整 `ns` 表达式,内部名称必须与位置参数完全匹配。
42
42
  - 最佳实践:优先使用 `add-import`(带保护和覆盖控制),`imports` 只在需要全量重置时使用。
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## 改动概要
4
4
 
5
- 新增 `cr edit split-def <ns/def> -p <path> -n <new-name>` 命令,用于将某定义内指定路径的子表达式提取为同命名空间内的一个新定义,原位置替换为新定义的名字。
5
+ 新增 `cr edit split-def <ns/def> --path <path> --name <new-name>` 命令,用于将某定义内指定路径的子表达式提取为同命名空间内的一个新定义,原位置替换为新定义的名字。
6
6
 
7
7
  ## 修改文件
8
8
 
9
- - `src/cli_args.rs`:新增 `EditSplitDefCommand` struct(参数:`target`, `-p/--path`, `-n/--name`);在 `EditSubcommand` 枚举中新增 `SplitDef(EditSplitDefCommand)` 变体。
9
+ - `src/cli_args.rs`:新增 `EditSplitDefCommand` struct(参数:`target`, `--path`, `--name`);在 `EditSubcommand` 枚举中新增 `SplitDef(EditSplitDefCommand)` 变体。
10
10
  - `src/bin/cli_handlers/edit.rs`:import 增加 `EditSplitDefCommand`;dispatch 增加 `EditSubcommand::SplitDef`;实现 `handle_split_def` 函数。
11
11
  - `docs/CalcitAgent.md`:
12
12
  1. 修复 `tree unwrap` 示例(移除已废弃的 `-i 1` 参数,更新描述为 splice 所有子节点语义)。
@@ -26,4 +26,4 @@
26
26
 
27
27
  - `split-def` 只操作 AST,不会自动添加 import。如果新定义需要被其他 ns 引用,需手动 `cr edit add-import`。
28
28
  - 路径索引规则与 `cr tree` 系列一致(逗号分隔,0-based)。
29
- - 提取后如需给新定义包装成 `defn` 函数形式,用 `cr tree replace <ns/new-name> -p '' -e 'defn new-name (args...) ...'`。
29
+ - 提取后如需给新定义包装成 `defn` 函数形式,用 `cr tree replace <ns/new-name> --path '' --code 'quote (defn new-name (args...) ...)'`。
@@ -12,7 +12,7 @@
12
12
 
13
13
  ## 命令语义
14
14
 
15
- ### `cr tree raise <ns/def> -p <child-path>`
15
+ ### `cr tree raise <ns/def> --path <child-path>`
16
16
 
17
17
  等价 Paredit `raise-sexp`。将指定子节点**整体替换掉其父节点**。
18
18
 
@@ -20,11 +20,11 @@
20
20
  - `parent_path = path[..n-1]`,用 `apply_operation_at_path(..., "replace", child)` 实现
21
21
  - 典型用途:去掉 `if` 只保留某分支、去掉 `let` 只保留最终返回值表达式
22
22
 
23
- ### `cr tree wrap <ns/def> -p <path> -e '<template>'`
23
+ ### `cr tree wrap <ns/def> --path <path> --code '<template>'`
24
24
 
25
- 等价 `cr tree rewrite ... -w 'self=.'`,但更简洁。模板中 `self` 自动绑定为原节点。
25
+ 等价 `cr tree rewrite ... --with 'self=.'`,但更简洁。模板中 `self` 自动绑定为原节点。
26
26
 
27
- - 适合"加一层调用"的常见模式:`wrap -e 'println self'`、`wrap -e 'let ((x self)) x'`
27
+ - 适合"加一层调用"的常见模式:`wrap --code 'println self'`、`wrap --code 'let ((x self)) x'`
28
28
  - 当需要引用原节点的**子节点**(不只是整体)时,仍需用 `rewrite --with`
29
29
 
30
30
  ## 知识点
@@ -8,9 +8,9 @@
8
8
  ## 新语法
9
9
 
10
10
  ```bash
11
- cr edit schema 'respo.comp.space/style-space' --leaf -e ':string'
12
- cr edit schema 'some.ns/my-val' --leaf -e ':number'
13
- cr edit schema 'some.ns/my-flag' --leaf -e ':bool'
11
+ cr edit schema 'respo.comp.space/style-space' --code 'quote :string'
12
+ cr edit schema 'some.ns/my-val' --code 'quote :number'
13
+ cr edit schema 'some.ns/my-flag' --code 'quote :bool'
14
14
  ```
15
15
 
16
16
  接受的 primitive 类型 tag:`bool`, `number`, `string`, `symbol`, `tag`, `list`, `map`, `set`, `fn`, `tuple`, `ref`, `buffer`, `dynamic`, `unit`
@@ -35,7 +35,7 @@ cr edit schema 'some.ns/my-flag' --leaf -e ':bool'
35
35
 
36
36
  ## 完整数据流(以 `:string` 为例)
37
37
 
38
- 1. CLI 收到 `--leaf -e ':string'` `Cirru::Leaf(":string")`
38
+ 1. CLI 收到 quoted schema 输入 `--code 'quote :string'`,取出 payload 后得到 `Cirru::Leaf(":string")`
39
39
  2. `validate_schema_for_write` → `"string"` 在 `PRIMITIVE_SCHEMA_TAGS` → Ok
40
40
  3. `CalcitTypeAnnotation::from_tag_name("string")` → `CalcitTypeAnnotation::String`
41
41
  4. 写入快照 → `CodeEntry::From` 序列化为 `Edn::tag("string")`
@@ -0,0 +1,14 @@
1
+ # 2026-07-26 12:20 to-js-data options validation
2
+
3
+ ## 修改概要
4
+
5
+ - 将 `to-js-data` 的第二参数改为 options map,并保留旧 boolean `addColon` 参数的兼容警告。
6
+ - 支持 `{} (:js-array true)`、`:js-object`、`:js-string`、`:js-number` 作为转换结果验证标记。
7
+ - 为 JS 集成测试和 `cr query examples calcit.core/to-js-data` 增加 options 示例。
8
+
9
+ ## 验证
10
+
11
+ - `yarn compile`
12
+ - `cargo test -q --bin cr`
13
+ - `yarn try-js`
14
+ - `cr calcit/test.cirru query examples calcit.core/to-js-data`
@@ -0,0 +1,12 @@
1
+ # 2026-07-26 12:44 Release 0.12.52
2
+
3
+ ## 修改概要
4
+
5
+ - 将 Rust crate 和 npm package 版本同步升级到 `0.12.52`。
6
+ - 执行 `cargo update --workspace` 更新锁文件元数据。
7
+
8
+ ## 发布前验证
9
+
10
+ - `yarn compile`
11
+ - `cargo test -q --bin cr`
12
+ - `yarn try-js`
@@ -0,0 +1,14 @@
1
+ # 2026-07-26 13:13 CLI 长参数提示修复
2
+
3
+ ## 修改概要
4
+
5
+ - 将 `remote-libs readme` 的过时 `-f` 提示统一为 `--file`。
6
+ - 修正 docs、edit、tree 与 markdown 提示中遗留的短参数,使用 CLI 当前公开的 `--filename`、`--context`、`--filter`、`--path`、`--code`、`--file`。
7
+
8
+ ## 验证
9
+
10
+ - `cargo fmt --all`
11
+ - `cargo run --bin cr -- docs remote-libs readme --help`
12
+ - `cargo run --bin cr -- docs search --help`
13
+ - `cargo run --bin cr -- query search --help`
14
+ - `cargo run --bin cr -- tree show --help`
@@ -0,0 +1,5 @@
1
+ # 方法字面量展示
2
+
3
+ - `Calcit::Method` 的展示与 `turn_string` 统一输出 Calcit 可写的字面量语法,例如 `.ceil`、`.display-by`。
4
+ - `defimpl` 与 `deftrait` 过去从 `format-to-lisp` 的 `(&invoke name)` 内部格式中截取方法名;展示改为 `.name` 后,需改为去掉首个点号并保留其余字符串。
5
+ - 验证应覆盖 Rust 测试、JS 编译运行,以及 `cr eval '&methods-of 1'` 的实际输出,避免 trait/impl 方法名在预处理时退化为 tuple 方法调用。
@@ -0,0 +1,11 @@
1
+ # Agent semantic interface RFC
2
+
3
+ ## 概要
4
+
5
+ - 新增 `07-26-agent-semantic-interface-roadmap-rfc.md`,系统整理 Snapshot AST、静态类型、文档知识图、结构化查询与事务编辑对 LLM Agent 的支撑路线。
6
+ - 在 RFC 索引中登记新路线图。
7
+ - 修正已有树形导航 RFC 中遗留的 `-p` 写法,统一为 `--path`。
8
+
9
+ ## 边界
10
+
11
+ 本批只固定后续开发方向和 CLI 词汇,不包含运行时或 Snapshot 数据变更。
@@ -0,0 +1,30 @@
1
+ # Static analysis and Agent CLI integration
2
+
3
+ ## 静态类型
4
+
5
+ - 将 `:any` 定义为明确的静态顶类型,与会双向擦除检查的 `:dynamic` 区分。
6
+ - 增强 list/map/set/ref、record/enum、callback、rest 参数与局部函数的类型推断和 schema 检查。
7
+ - 让 type coverage/weak-types 输出稳定 JSON、详细路径、建议与 `--summary-only` 汇总。
8
+
9
+ ## Agent 语义查询
10
+
11
+ - 增强 `cr query schema/type/type-at/context/search/search-expr`,提供带 revision 的机器可读结果。
12
+ - 缩小查询时的 Snapshot/module 加载范围,并为定义 examples 增加精确检查入口。
13
+ - 增加 `yarn check-agent-interface`,验证 JSON stdout 协议并记录查询耗时与输出体积。
14
+
15
+ ## CLI 编辑完整性
16
+
17
+ - Cirru AST 输入严格使用 `quote` 作为代码/数据边界,不再把普通 EDN 误当代码。
18
+ - `edit schema` 要求单个 quoted node;批量 `edit examples` 要求每个顶层节点独立 `quote`,从而同时可表示 leaf 和表达式。
19
+ - `query examples` 直接显示 leaf;rename/move 定义时同步更新声明名称。
20
+ - 清理文档与提示中的历史短参数,统一为明确的长参数词汇。
21
+
22
+ ## 验证
23
+
24
+ - `cargo fmt --all`
25
+ - `cargo test`
26
+ - `cargo clippy -- -D warnings`
27
+ - `yarn compile`
28
+ - `yarn check-all`
29
+ - `cr docs check-md docs/CalcitAgent.md --entry calcit/test.cirru --failures-only`
30
+ - 通过 Snapshot 临时副本验证 schema/examples 的 quoted expression、quoted leaf 与裸输入拒绝路径。
@@ -0,0 +1,7 @@
1
+ # Replace the legacy bundle CLI with a Calcit script
2
+
3
+ - Removed the deprecated `bundle_calcit` Rust binary and its release artifact.
4
+ - Added the recursive `read-dir` Calcit runtime API so filesystem workflows can be implemented in Calcit.
5
+ - Added `calcit/bundle-calcit.cirru` as a directly executable snapshot that bundles indentation-based source files into a runnable snapshot.
6
+ - Updated installation and bundle-mode documentation to use the script-based workflow.
7
+ - Verified the script against `minimal-calcit`, including loading and running the generated snapshot.
@@ -0,0 +1,7 @@
1
+ # Replace the legacy cr-sync binary with a Calcit script
2
+
3
+ - Removed the `cr-sync` Rust binary and its installation documentation.
4
+ - Moved the bundle script to `calcit/scripts/` and added `sync-calcit.cirru` beside it.
5
+ - Added `unix-time-ms` for script-generated snapshot metadata.
6
+ - Reused `bisection-key` lexical-key APIs; `bisection-key` 0.0.18 fixes string-key append support.
7
+ - Verified synchronization against the editor repository's real `compact.cirru` and `calcit.cirru` fixtures, then checked the output with the legacy dry-run binary.
@@ -0,0 +1,17 @@
1
+ # 2026-07-28 caps 模块状态检查与重置
2
+
3
+ ## 修改概要
4
+
5
+ - 为 `caps` 增加 `status` 子命令,检查 `deps.cirru` 声明模块的版本、缺失状态和本地 Git 修改。
6
+ - 为 `caps` 增加 `reset` 子命令,重置已安装模块的 tracked 本地修改。
7
+ - 普通 `caps` 同步前增加本地模块状态提示。
8
+ - 补充依赖加载文档。
9
+
10
+ ## 验证
11
+
12
+ - `cargo fmt`
13
+ - `cargo clippy -- -D warnings`
14
+ - `cargo test`
15
+ - `yarn compile`
16
+ - `yarn check-all`
17
+ - `yarn check-agent-interface`
@@ -0,0 +1,6 @@
1
+ # 2026-07-28 发布 0.12.53
2
+
3
+ ## 修改概要
4
+
5
+ - 同步 `Cargo.toml` 和 `package.json` 版本号到 `0.12.53`。
6
+ - 执行 `cargo update --workspace` 更新 `Cargo.lock`。
@@ -60,13 +60,13 @@
60
60
  - 可见 `--detail-offset` 参数。
61
61
  - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search --help`
62
62
  - `--start-path` 示例为点号格式。
63
- - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search state -f respo.app.comp.todolist/comp-todolist --detail-offset 5`
63
+ - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search state --filter respo.app.comp.todolist/comp-todolist --detail-offset 5`
64
64
  - 输出降噪,路径为点号,窗口外压缩。
65
- - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search state -f respo.app.comp.todolist/comp-todolist --detail-offset 0`
65
+ - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search state --filter respo.app.comp.todolist/comp-todolist --detail-offset 0`
66
66
  - 详情窗口为 `[0, 3)`,每条命中仅展示一行(优先父节点预览)。
67
- - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search state -f respo.app.comp.todolist/comp-todolist --detail-offset 0 --exact`
67
+ - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search state --filter respo.app.comp.todolist/comp-todolist --detail-offset 0 --exact`
68
68
  - 精确命中不再把 `states` 视觉误判为 `state`;且不显示“add --exact”提示。
69
- - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search-expr state -f respo.app.comp.todolist/comp-todolist --detail-offset 0`
69
+ - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search-expr state --filter respo.app.comp.todolist/comp-todolist --detail-offset 0`
70
70
  - 输出样式一致(单行预览)。
71
- - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search-expr state -f respo.app.comp.todolist/comp-todolist --detail-offset 0 --exact`
71
+ - `cargo run --bin cr -- /Users/jon.chen/repo/respo/respo/calcit.cirru query search-expr state --filter respo.app.comp.todolist/comp-todolist --detail-offset 0 --exact`
72
72
  - 结果为 `No matches found`,符合结构精确匹配预期。
@@ -60,8 +60,8 @@
60
60
  - `cargo run --bin cr -- calcit/test.cirru analyze js-unescape 'demo_$q_'`
61
61
  - `cargo run --bin cr -- calcit/test.cirru query ns app.main`
62
62
  - `cargo run --bin cr -- calcit/test.cirru query find render`
63
- - `cargo run --bin cr -- calcit/test.cirru tree show app.main/test-json -p ''`
64
- - `cargo run --bin cr -- calcit/test.cirru docs search chunk -f agent-advanced.md`
63
+ - `cargo run --bin cr -- calcit/test.cirru tree show app.main/test-json --path ''`
64
+ - `cargo run --bin cr -- calcit/test.cirru docs search chunk --filename agent-advanced.md`
65
65
  - `cargo run --bin cr -- demos/calcit.cirru docs check-md docs/CalcitAgent.md`
66
66
  - `cargo run --bin cr -- /tmp/calcit-cli-demo/calcit.cirru tree replace ...` 多次人工检查 replace 输出形态
67
67
 
@@ -32,7 +32,7 @@ export declare let castTag: (x: CalcitValue) => CalcitTag;
32
32
  export declare var refsRegistry: Map<string, CalcitRef>;
33
33
  export declare let hashFunction: (x: CalcitValue) => Hash;
34
34
  export declare let toString: (x: CalcitValue, escaped: boolean, disableJsDataWarning?: boolean) => string;
35
- export declare let to_js_data: (x: CalcitValue, addColon?: boolean) => any;
35
+ export declare let to_js_data: (x: CalcitValue, options?: CalcitValue | boolean) => any;
36
36
  export declare let _$n_map_$o_get: (xs: CalcitValue, k: CalcitValue) => CalcitValue;
37
37
  export declare let _$n__$e_: (x: CalcitValue, y: CalcitValue) => boolean;
38
38
  /** special trick for disabling ternary tree list check */
@@ -441,7 +441,38 @@ export let toString = (x, escaped, disableJsDataWarning = false) => {
441
441
  }
442
442
  return `(#js ${JSON.stringify(x)})`;
443
443
  };
444
- export let to_js_data = (x, addColon = false) => {
444
+ export let to_js_data = (x, options) => {
445
+ let addColon = false;
446
+ if (typeof options === "boolean") {
447
+ console.warn("to-js-data: the addColon boolean argument is deprecated; pass an options map instead");
448
+ addColon = options;
449
+ }
450
+ else if (options !== undefined) {
451
+ let jsOptions = to_js_data_inner(options, false);
452
+ addColon = jsOptions[":add-colon"] === true || jsOptions["add-colon"] === true;
453
+ let value = to_js_data_inner(x, addColon);
454
+ let expectedType = jsOptions[":type"] ??
455
+ jsOptions.type ??
456
+ (jsOptions[":js-array"] || jsOptions["js-array"] ? "js-array" : undefined) ??
457
+ (jsOptions[":js-string"] || jsOptions["js-string"] ? "js-string" : undefined) ??
458
+ (jsOptions[":js-number"] || jsOptions["js-number"] ? "js-number" : undefined) ??
459
+ (jsOptions[":js-object"] || jsOptions["js-object"] ? "js-object" : undefined) ??
460
+ "js-object";
461
+ let valid = (expectedType === "js-array" && Array.isArray(value)) ||
462
+ (expectedType === "js-object" &&
463
+ value !== null &&
464
+ typeof value === "object" &&
465
+ !Array.isArray(value) &&
466
+ !(value instanceof Set)) ||
467
+ (expectedType === "js-string" && typeof value === "string") ||
468
+ (expectedType === "js-number" && typeof value === "number");
469
+ if (!valid)
470
+ throw new Error(`to-js-data expects ${expectedType}`);
471
+ return value;
472
+ }
473
+ return to_js_data_inner(x, addColon);
474
+ };
475
+ let to_js_data_inner = (x, addColon) => {
445
476
  if (x == null) {
446
477
  return null;
447
478
  }
@@ -470,17 +501,17 @@ export let to_js_data = (x, addColon = false) => {
470
501
  return Symbol(x.value);
471
502
  }
472
503
  if (x instanceof CalcitTuple) {
473
- var result = [to_js_data(x.tag)];
504
+ var result = [to_js_data_inner(x.tag, false)];
474
505
  for (let i = 0; i < x.extra.length; i++) {
475
506
  let item = x.extra[i];
476
- result.push(to_js_data(item));
507
+ result.push(to_js_data_inner(item, false));
477
508
  }
478
509
  return result;
479
510
  }
480
511
  if (x instanceof CalcitList || x instanceof CalcitSliceList) {
481
512
  var result = [];
482
513
  for (let item of x.items()) {
483
- result.push(to_js_data(item, addColon));
514
+ result.push(to_js_data_inner(item, addColon));
484
515
  }
485
516
  return result;
486
517
  }
@@ -490,22 +521,22 @@ export let to_js_data = (x, addColon = false) => {
490
521
  for (let idx = 0; idx < pairs.length; idx++) {
491
522
  let k = pairs[idx][0];
492
523
  let v = pairs[idx][1];
493
- var key = to_js_data(k, addColon);
494
- result[key] = to_js_data(v, addColon);
524
+ var key = to_js_data_inner(k, addColon);
525
+ result[key] = to_js_data_inner(v, addColon);
495
526
  }
496
527
  return result;
497
528
  }
498
529
  if (x instanceof CalcitSet) {
499
530
  let result = new Set();
500
531
  x.values().forEach((v) => {
501
- result.add(to_js_data(v, addColon));
532
+ result.add(to_js_data_inner(v, addColon));
502
533
  });
503
534
  return result;
504
535
  }
505
536
  if (x instanceof CalcitRecord) {
506
537
  let result = {};
507
538
  for (let idx = 0; idx < x.fields.length; idx++) {
508
- result[x.fields[idx].value] = to_js_data(x.values[idx]);
539
+ result[x.fields[idx].value] = to_js_data_inner(x.values[idx], false);
509
540
  }
510
541
  return result;
511
542
  }
@@ -20,6 +20,7 @@ export declare const calcit_package_json: {
20
20
  "bench-recur-smoke": string;
21
21
  "check-smooth": string;
22
22
  "check-all": string;
23
+ "check-agent-interface": string;
23
24
  "try-all": string;
24
25
  "try-rs": string;
25
26
  "warn-dyn-method": string;
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.12.51",
3
+ "version": "0.12.53",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.7.0",
@@ -18,7 +18,8 @@
18
18
  "test-snippets": "cargo test -q snippets::tests",
19
19
  "bench-recur-smoke": "cargo run --bin cr -- calcit/test.cirru js && node --input-type=module -e \"import { test_loop } from './js-out/test-recursion.main.mjs'; const n=3000; const t0=process.hrtime.bigint(); for(let i=0;i<n;i++) test_loop(); const dt=Number(process.hrtime.bigint()-t0)/1e6; console.log('test_loop_ms='+dt.toFixed(3));\"",
20
20
  "check-smooth": "yarn fmt-rs && yarn lint-rs && yarn test-rs && yarn check-all",
21
- "check-all": "yarn compile && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm",
21
+ "check-all": "yarn compile && yarn check-agent-interface && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm",
22
+ "check-agent-interface": "cargo build --bin cr && node scripts/check-agent-interface.mjs",
22
23
  "try-all": "yarn check-all",
23
24
  "try-rs": "cargo run --bin cr -- calcit/test.cirru",
24
25
  "warn-dyn-method": "cargo run --bin cr -- calcit/test.cirru --warn-dyn-method",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calcit/procs",
3
- "version": "0.12.51",
3
+ "version": "0.12.53",
4
4
  "main": "./lib/calcit.procs.mjs",
5
5
  "devDependencies": {
6
6
  "@types/node": "^25.7.0",
@@ -18,7 +18,8 @@
18
18
  "test-snippets": "cargo test -q snippets::tests",
19
19
  "bench-recur-smoke": "cargo run --bin cr -- calcit/test.cirru js && node --input-type=module -e \"import { test_loop } from './js-out/test-recursion.main.mjs'; const n=3000; const t0=process.hrtime.bigint(); for(let i=0;i<n;i++) test_loop(); const dt=Number(process.hrtime.bigint()-t0)/1e6; console.log('test_loop_ms='+dt.toFixed(3));\"",
20
20
  "check-smooth": "yarn fmt-rs && yarn lint-rs && yarn test-rs && yarn check-all",
21
- "check-all": "yarn compile && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm",
21
+ "check-all": "yarn compile && yarn check-agent-interface && yarn try-rs && yarn try-js && yarn try-ir && yarn try-wasm",
22
+ "check-agent-interface": "cargo build --bin cr && node scripts/check-agent-interface.mjs",
22
23
  "try-all": "yarn check-all",
23
24
  "try-rs": "cargo run --bin cr -- calcit/test.cirru",
24
25
  "warn-dyn-method": "cargo run --bin cr -- calcit/test.cirru --warn-dyn-method",
@@ -472,7 +472,39 @@ export let toString = (x: CalcitValue, escaped: boolean, disableJsDataWarning: b
472
472
  return `(#js ${JSON.stringify(x)})`;
473
473
  };
474
474
 
475
- export let to_js_data = (x: CalcitValue, addColon: boolean = false): any => {
475
+ export let to_js_data = (x: CalcitValue, options?: CalcitValue | boolean): any => {
476
+ let addColon = false;
477
+ if (typeof options === "boolean") {
478
+ console.warn("to-js-data: the addColon boolean argument is deprecated; pass an options map instead");
479
+ addColon = options;
480
+ } else if (options !== undefined) {
481
+ let jsOptions = to_js_data_inner(options, false) as Record<string, any>;
482
+ addColon = jsOptions[":add-colon"] === true || jsOptions["add-colon"] === true;
483
+ let value = to_js_data_inner(x, addColon);
484
+ let expectedType =
485
+ jsOptions[":type"] ??
486
+ jsOptions.type ??
487
+ (jsOptions[":js-array"] || jsOptions["js-array"] ? "js-array" : undefined) ??
488
+ (jsOptions[":js-string"] || jsOptions["js-string"] ? "js-string" : undefined) ??
489
+ (jsOptions[":js-number"] || jsOptions["js-number"] ? "js-number" : undefined) ??
490
+ (jsOptions[":js-object"] || jsOptions["js-object"] ? "js-object" : undefined) ??
491
+ "js-object";
492
+ let valid =
493
+ (expectedType === "js-array" && Array.isArray(value)) ||
494
+ (expectedType === "js-object" &&
495
+ value !== null &&
496
+ typeof value === "object" &&
497
+ !Array.isArray(value) &&
498
+ !(value instanceof Set)) ||
499
+ (expectedType === "js-string" && typeof value === "string") ||
500
+ (expectedType === "js-number" && typeof value === "number");
501
+ if (!valid) throw new Error(`to-js-data expects ${expectedType}`);
502
+ return value;
503
+ }
504
+ return to_js_data_inner(x, addColon);
505
+ };
506
+
507
+ let to_js_data_inner = (x: CalcitValue, addColon: boolean): any => {
476
508
  if (x == null) {
477
509
  return null;
478
510
  }
@@ -501,17 +533,17 @@ export let to_js_data = (x: CalcitValue, addColon: boolean = false): any => {
501
533
  return Symbol(x.value);
502
534
  }
503
535
  if (x instanceof CalcitTuple) {
504
- var result: any[] = [to_js_data(x.tag)];
536
+ var result: any[] = [to_js_data_inner(x.tag, false)];
505
537
  for (let i = 0; i < x.extra.length; i++) {
506
538
  let item = x.extra[i];
507
- result.push(to_js_data(item));
539
+ result.push(to_js_data_inner(item, false));
508
540
  }
509
541
  return result;
510
542
  }
511
543
  if (x instanceof CalcitList || x instanceof CalcitSliceList) {
512
544
  var result: any[] = [];
513
545
  for (let item of x.items()) {
514
- result.push(to_js_data(item, addColon));
546
+ result.push(to_js_data_inner(item, addColon));
515
547
  }
516
548
  return result;
517
549
  }
@@ -521,22 +553,22 @@ export let to_js_data = (x: CalcitValue, addColon: boolean = false): any => {
521
553
  for (let idx = 0; idx < pairs.length; idx++) {
522
554
  let k = pairs[idx][0];
523
555
  let v = pairs[idx][1];
524
- var key = to_js_data(k, addColon);
525
- result[key] = to_js_data(v, addColon);
556
+ var key = to_js_data_inner(k, addColon);
557
+ result[key] = to_js_data_inner(v, addColon);
526
558
  }
527
559
  return result;
528
560
  }
529
561
  if (x instanceof CalcitSet) {
530
562
  let result = new Set();
531
563
  x.values().forEach((v) => {
532
- result.add(to_js_data(v, addColon));
564
+ result.add(to_js_data_inner(v, addColon));
533
565
  });
534
566
  return result;
535
567
  }
536
568
  if (x instanceof CalcitRecord) {
537
569
  let result: Record<string, CalcitValue> = {};
538
570
  for (let idx = 0; idx < x.fields.length; idx++) {
539
- result[x.fields[idx].value] = to_js_data(x.values[idx]);
571
+ result[x.fields[idx].value] = to_js_data_inner(x.values[idx], false);
540
572
  }
541
573
  return result;
542
574
  }