@runko/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # @runko/sdk
2
+
3
+ runko 的主包(门面):batteries-included,re-export 全部三个子包(`@runko/core` / `@runko/virtual-fs` / `@runko/mini-bash`),5 行上手只装这一个。
4
+
5
+ > TODO:npm 裸名 `runko` 的发布决策待定——定了之后本 README 与所有示例的 `@runko/sdk` import 同步替换。
6
+
7
+ ## 安装
8
+
9
+ ```sh
10
+ pnpm add @runko/sdk ai # ai@^7 是 peerDependency,跟随宿主版本
11
+ ```
12
+
13
+ 模型层即 Vercel AI SDK:`"provider/model"` Gateway 字符串开箱可用(零 provider 依赖);要直连某家 provider 就再装对应包(如 `@ai-sdk/anthropic`)。
14
+
15
+ ## 最小用例(产品文档 §4.1 的五行示例)
16
+
17
+ ```ts
18
+ import { defineAgent, createSession, RunkoFS } from "@runko/sdk";
19
+ // 或直连 provider:import { anthropic } from "@ai-sdk/anthropic"; model: anthropic("claude-sonnet-5")
20
+
21
+ const agent = defineAgent({ model: "anthropic/claude-sonnet-5" });
22
+ const session = createSession(agent, { fs: RunkoFS.fromDirectory("./project") });
23
+ const result = await session.send("把 src/index.ts 里的 var 全部改成 const");
24
+ console.log(result.finalResponse, await session.fs.diff());
25
+ ```
26
+
27
+ 全程不写真实磁盘——写入落在 overlay 内存层,`session.fs.diff()` 拿变更,`session.fs.writeBack()` 才落盘(唯一写磁盘的操作,只有宿主可达)。
28
+
29
+ ## 本包相对 @runko/core 的两处默认装配
30
+
31
+ 其余 API 全部原样 re-export(清单见各子包 README);本包自己只添两个符号:
32
+
33
+ ### `createSession(agent, opts?)`(默认装配版)
34
+
35
+ 与 core 的原始 `createSession` 同名同形状,差异只在默认值:
36
+
37
+ - **`fs` 缺省时自动注入空 `MemoryFS`**(core 版缺省是"调用即抛指导性错误"的占位 FS);
38
+ - **文件工具八件套默认全开**(read_file / write_file / edit_file / delete_file / move_file / list_dir / glob / grep,`@runko/virtual-fs` 的 `createFileTools` 自动拼装,readState / file_change 事件通路全接好);`agent.builtinTools` 数组白名单裁剪、`false` 全关;宿主 `tools` 同名覆盖内置。
39
+ - **`session.fs` 保留传入的具体类型**:`fs: RunkoFS.fromDirectory(...)` 时 `session.fs` 就是 `OverlayFS`,`session.fs.diff()` 无需断言直接编译(三重载泛型)。
40
+
41
+ 需要无装配原语的宿主直接 `import { createSession } from "@runko/core"`,路径未被遮蔽切断。
42
+
43
+ ### `RunkoFS`(类型 + 值命名空间)
44
+
45
+ - 类型:即 core 的 `RunkoFS` 接口(七方法:readFile / writeFile / rm / mkdir / readdir / stat / glob)。
46
+ - 值:`RunkoFS.fromMemory(files)` → `MemoryFS`;`RunkoFS.fromDirectory(dir, opts?)` → `OverlayFS`(真实目录零拷贝挂载)。
47
+
48
+ ## 常用能力速查(均经本包可达)
49
+
50
+ | 要做什么 | 用什么 | 定义在 |
51
+ |---|---|---|
52
+ | 声明 agent / 工具 / skill | `defineAgent` / `defineTool` / `defineSkill` | [@runko/core](../core/README.md) |
53
+ | 跑会话、流式事件、审批、序列化恢复 | `createSession` → `send()` / `stream()` / `toJSON()` + `SessionOptions.resume` | @runko/core(本包加默认装配) |
54
+ | 结构化输出 | `session.send<T>(input, { outputSchema })` | @runko/core |
55
+ | 虚拟文件系统 | `RunkoFS.fromMemory` / `RunkoFS.fromDirectory`、`diff()` / `writeBack()` / `snapshot()` | [@runko/virtual-fs](../virtual-fs/README.md) |
56
+ | 纯内存命令执行(bash 工具,零依赖极简档:六命令) | `createSession(agent, { fs, exec: miniBash(fs) })` | [@runko/mini-bash](../mini-bash/README.md) |
57
+ | 全语法档命令执行(bash 工具:`if`/`for`/`while`/`case`/函数) | `createSession(agent, { fs, exec: justBash(fs) })`——**需单独 `pnpm add @runko/just-bash`**,不随本包装入 | [@runko/just-bash](../just-bash/README.md) |
58
+ | 本机命令执行 | `localExec()`(出厂审批 `"always"`;`{ materialize: true, fs }` 物化模式) | @runko/core |
59
+ | eve 布局目录加载 | `loadAgent(dir)` / `loadAgentFromFS(fs, dir)`(`@runko/core/load` 子路径同样可达) | @runko/core |
60
+
61
+ **bash 分档**:`@runko/mini-bash` 随本包 re-export,开箱可用,定位安全默认/测试演示;`@runko/just-bash`(vercel-labs/just-bash 适配器)因依赖树含 wasm 大件(sql.js、quickjs-emscripten 等)**不进本包依赖**,强制打包违背门面轻量默认——需要全语法档的宿主显式安装该包后按上表用法注入(见 [core-sdk · 技术方案 §4.5b](../../docs/logic/engine/tech/core-sdk.md))。
62
+
63
+ 可运行示例见 [examples/](../../examples/README.md)(含 [08-just-bash.ts](../../examples/src/08-just-bash.ts))。
package/dist/index.cjs ADDED
@@ -0,0 +1,131 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _runko_core = require("@runko/core");
3
+ let _runko_virtual_fs = require("@runko/virtual-fs");
4
+ //#region src/fs.ts
5
+ /**
6
+ * `RunkoFS` 值命名空间(docs/tech/core-sdk.md §4.4 原文字面调用形态:`RunkoFS.fromMemory(...)`/
7
+ * `RunkoFS.fromDirectory(...)`)。P2-1 施工时把工厂拆成 `@runko/virtual-fs` 的
8
+ * 独立函数 `fromMemory`/`fromDirectory`——因为 `RunkoFS` 本身已经是 `@runko/core`
9
+ * 导出的**接口类型**名,interface(跨包)与值命名空间没法通过声明合并凑到一起
10
+ * (合并只在单个模块内生效,且合并双方都必须是"本地声明",见下);tech-spec
11
+ * §4.4 原文把这层"重新拼回值命名空间"的工作留给门面(P7)评审,这里落地。
12
+ *
13
+ * 类型 `RunkoFS`(下方 `type RunkoFS = CoreRunkoFS`,与 core 的接口结构完全一致)
14
+ * 与值 `RunkoFS`(下方 `const RunkoFS`,两个工厂方法)分属 TypeScript 类型/值两个
15
+ * 独立命名空间,同名共存不冲突——与 core 自己的 `Skill`(`interface Skill` +
16
+ * `const Skill`,同一个模块内共存,P5-1 已验证的先例)是同一手法,唯一区别是这里
17
+ * 两半来自不同的包,在门面 `fs.ts` 首次汇合。
18
+ *
19
+ * 类型这里必须重新声明为**本地** `type RunkoFS = CoreRunkoFS`,不能写
20
+ * `export type { RunkoFS } from "@runko/core"` 原样透传——后者是一条"再导出"
21
+ * 语句而非本地类型声明,与下面的本地 `const RunkoFS` 搭配会被 tsc 判为
22
+ * "Cannot redeclare exported variable 'RunkoFS'"(TS2323);只有类型别名与值
23
+ * 两者都是货真价实的本地声明时才能合法合并。同理,`index.ts` 汇总本文件时也
24
+ * 必须用具名 re-export(`export { RunkoFS } from "./fs.js"`)而非 `export *`——
25
+ * 否则会与 `export * from "@runko/core"` 带入的 `RunkoFS` 类型撞成两个 `export *`
26
+ * 源导出同名成员的"ambiguous"错误(TS2308,与类型/值是否同一命名空间无关,
27
+ * tsc 按导出名字符串判定冲突)。两处结论均以最小复现验证过,详见工单汇报。
28
+ */
29
+ const RunkoFS = {
30
+ fromMemory: _runko_virtual_fs.fromMemory,
31
+ fromDirectory: _runko_virtual_fs.fromDirectory
32
+ };
33
+ //#endregion
34
+ //#region src/session.ts
35
+ /** 八件套的全部工具名,按 docs/tech/builtin-tools.md §1.1–§1.8 的声明顺序列出。 */
36
+ const ALL_FILE_TOOL_NAMES = [
37
+ "read-file",
38
+ "write-file",
39
+ "edit-file",
40
+ "delete-file",
41
+ "move-file",
42
+ "list-dir",
43
+ "glob",
44
+ "grep"
45
+ ];
46
+ /**
47
+ * `agent.builtinTools` 对文件工具八件套的过滤(docs/tech/builtin-tools.md §3):
48
+ * `false` 全关;`undefined`(未配置)默认全开;数组按白名单交集(数组里
49
+ * 出现的 `update-plan`/其他非文件工具名对这里无意义,交集自然把它们滤掉——
50
+ * `update-plan` 的开关逻辑仍由 core 自己的 `isUpdatePlanEnabled` 负责,两条
51
+ * 过滤各自独立、互不影响)。
52
+ */
53
+ function resolveEnabledFileToolNames(builtinTools) {
54
+ if (builtinTools === false) return [];
55
+ if (builtinTools === void 0) return ALL_FILE_TOOL_NAMES;
56
+ const requested = new Set(builtinTools);
57
+ return ALL_FILE_TOOL_NAMES.filter((name) => requested.has(name));
58
+ }
59
+ /**
60
+ * 预构造 `readState`/`derivedData` store 并拼出过滤后的文件工具八件套——
61
+ * 沿用 core `session.ts` 文件头记录的宿主装配姿态(`createFileTools({ readState,
62
+ * onFileChange })`,`onFileChange` 把 `FileChange[]` 逐条转发进
63
+ * `derivedData.recordFileChange`),只是这里由 sdk 在 `createSession(...)` 内部
64
+ * 自动完成,宿主不需要再手写这段拼装(P4-2 集成测试里手写的那段,正是这里的
65
+ * 落地位置)。
66
+ */
67
+ function buildDefaultFileTools(agent, readState, derivedData) {
68
+ const enabledNames = resolveEnabledFileToolNames(agent.builtinTools);
69
+ if (enabledNames.length === 0) return {};
70
+ const allFileTools = (0, _runko_virtual_fs.createFileTools)({
71
+ readState,
72
+ onFileChange: (changes) => {
73
+ for (const change of changes) derivedData.recordFileChange(change);
74
+ }
75
+ });
76
+ const enabled = {};
77
+ for (const name of enabledNames) enabled[name] = allFileTools[name];
78
+ return enabled;
79
+ }
80
+ /** `fs`/`workspace` 都未提供时才注入默认 `MemoryFS`——两者任一存在都原样透传给 core 自行解析(含互斥校验与 exec 派生)。 */
81
+ function withDefaultFs(opts) {
82
+ if (opts.fs !== void 0 || opts.workspace !== void 0) return opts;
83
+ return {
84
+ ...opts,
85
+ fs: new _runko_virtual_fs.MemoryFS()
86
+ };
87
+ }
88
+ function createSession(agent, opts = {}) {
89
+ const readState = opts.readState ?? (0, _runko_core.createSessionReadState)();
90
+ const derivedData = opts.derivedData ?? (0, _runko_core.createDerivedDataCollector)();
91
+ const tools = {
92
+ ...buildDefaultFileTools(agent, readState, derivedData),
93
+ ...agent.tools ?? {}
94
+ };
95
+ return (0, _runko_core.createSession)({
96
+ ...agent,
97
+ tools
98
+ }, withDefaultFs({
99
+ ...opts,
100
+ readState,
101
+ derivedData
102
+ }));
103
+ }
104
+ //#endregion
105
+ exports.RunkoFS = RunkoFS;
106
+ exports.createSession = createSession;
107
+ Object.keys(_runko_core).forEach(function(k) {
108
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
109
+ enumerable: true,
110
+ get: function() {
111
+ return _runko_core[k];
112
+ }
113
+ });
114
+ });
115
+ Object.keys(_runko_virtual_fs).forEach(function(k) {
116
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
117
+ enumerable: true,
118
+ get: function() {
119
+ return _runko_virtual_fs[k];
120
+ }
121
+ });
122
+ });
123
+ var _runko_mini_bash = require("@runko/mini-bash");
124
+ Object.keys(_runko_mini_bash).forEach(function(k) {
125
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
126
+ enumerable: true,
127
+ get: function() {
128
+ return _runko_mini_bash[k];
129
+ }
130
+ });
131
+ });
@@ -0,0 +1,26 @@
1
+ import { AgentDefinition, RunkoExec, RunkoFS as RunkoFS$1, Session as Session$1, SessionOptions } from "@runko/core";
2
+ import { MemoryFS, fromDirectory, fromMemory } from "@runko/virtual-fs";
3
+ export * from "@runko/core";
4
+ export * from "@runko/virtual-fs";
5
+ export * from "@runko/mini-bash";
6
+ //#region src/fs.d.ts
7
+ type RunkoFS = RunkoFS$1;
8
+ declare const RunkoFS: {
9
+ fromMemory: typeof fromMemory;
10
+ fromDirectory: typeof fromDirectory;
11
+ };
12
+ //#endregion
13
+ //#region src/session.d.ts
14
+ /** sdk 门面版 `Session`:与 core 的原始 `Session` 完全一致,只是 `fs` 保留调用方传入的具体类型。 */
15
+ type Session<F extends RunkoFS$1 = RunkoFS$1> = Omit<Session$1, "fs"> & {
16
+ readonly fs: F;
17
+ };
18
+ declare function createSession<F extends RunkoFS$1>(agent: AgentDefinition, opts: Omit<SessionOptions, "fs" | "workspace"> & {
19
+ fs: F;
20
+ }): Session<F>;
21
+ declare function createSession<W extends RunkoFS$1 & RunkoExec>(agent: AgentDefinition, opts: Omit<SessionOptions, "fs" | "workspace"> & {
22
+ workspace: W;
23
+ }): Session<W>;
24
+ declare function createSession(agent: AgentDefinition, opts?: SessionOptions): Session<MemoryFS>;
25
+ //#endregion
26
+ export { RunkoFS, type Session, createSession };
@@ -0,0 +1,26 @@
1
+ import { AgentDefinition, RunkoExec, RunkoFS as RunkoFS$1, Session as Session$1, SessionOptions } from "@runko/core";
2
+ import { MemoryFS, fromDirectory, fromMemory } from "@runko/virtual-fs";
3
+ export * from "@runko/core";
4
+ export * from "@runko/virtual-fs";
5
+ export * from "@runko/mini-bash";
6
+ //#region src/fs.d.ts
7
+ type RunkoFS = RunkoFS$1;
8
+ declare const RunkoFS: {
9
+ fromMemory: typeof fromMemory;
10
+ fromDirectory: typeof fromDirectory;
11
+ };
12
+ //#endregion
13
+ //#region src/session.d.ts
14
+ /** sdk 门面版 `Session`:与 core 的原始 `Session` 完全一致,只是 `fs` 保留调用方传入的具体类型。 */
15
+ type Session<F extends RunkoFS$1 = RunkoFS$1> = Omit<Session$1, "fs"> & {
16
+ readonly fs: F;
17
+ };
18
+ declare function createSession<F extends RunkoFS$1>(agent: AgentDefinition, opts: Omit<SessionOptions, "fs" | "workspace"> & {
19
+ fs: F;
20
+ }): Session<F>;
21
+ declare function createSession<W extends RunkoFS$1 & RunkoExec>(agent: AgentDefinition, opts: Omit<SessionOptions, "fs" | "workspace"> & {
22
+ workspace: W;
23
+ }): Session<W>;
24
+ declare function createSession(agent: AgentDefinition, opts?: SessionOptions): Session<MemoryFS>;
25
+ //#endregion
26
+ export { RunkoFS, type Session, createSession };
package/dist/index.js ADDED
@@ -0,0 +1,107 @@
1
+ import { createDerivedDataCollector, createSession as createSession$1, createSessionReadState } from "@runko/core";
2
+ import { MemoryFS, createFileTools, fromDirectory, fromMemory } from "@runko/virtual-fs";
3
+ export * from "@runko/core";
4
+ export * from "@runko/virtual-fs";
5
+ export * from "@runko/mini-bash";
6
+ //#region src/fs.ts
7
+ /**
8
+ * `RunkoFS` 值命名空间(docs/tech/core-sdk.md §4.4 原文字面调用形态:`RunkoFS.fromMemory(...)`/
9
+ * `RunkoFS.fromDirectory(...)`)。P2-1 施工时把工厂拆成 `@runko/virtual-fs` 的
10
+ * 独立函数 `fromMemory`/`fromDirectory`——因为 `RunkoFS` 本身已经是 `@runko/core`
11
+ * 导出的**接口类型**名,interface(跨包)与值命名空间没法通过声明合并凑到一起
12
+ * (合并只在单个模块内生效,且合并双方都必须是"本地声明",见下);tech-spec
13
+ * §4.4 原文把这层"重新拼回值命名空间"的工作留给门面(P7)评审,这里落地。
14
+ *
15
+ * 类型 `RunkoFS`(下方 `type RunkoFS = CoreRunkoFS`,与 core 的接口结构完全一致)
16
+ * 与值 `RunkoFS`(下方 `const RunkoFS`,两个工厂方法)分属 TypeScript 类型/值两个
17
+ * 独立命名空间,同名共存不冲突——与 core 自己的 `Skill`(`interface Skill` +
18
+ * `const Skill`,同一个模块内共存,P5-1 已验证的先例)是同一手法,唯一区别是这里
19
+ * 两半来自不同的包,在门面 `fs.ts` 首次汇合。
20
+ *
21
+ * 类型这里必须重新声明为**本地** `type RunkoFS = CoreRunkoFS`,不能写
22
+ * `export type { RunkoFS } from "@runko/core"` 原样透传——后者是一条"再导出"
23
+ * 语句而非本地类型声明,与下面的本地 `const RunkoFS` 搭配会被 tsc 判为
24
+ * "Cannot redeclare exported variable 'RunkoFS'"(TS2323);只有类型别名与值
25
+ * 两者都是货真价实的本地声明时才能合法合并。同理,`index.ts` 汇总本文件时也
26
+ * 必须用具名 re-export(`export { RunkoFS } from "./fs.js"`)而非 `export *`——
27
+ * 否则会与 `export * from "@runko/core"` 带入的 `RunkoFS` 类型撞成两个 `export *`
28
+ * 源导出同名成员的"ambiguous"错误(TS2308,与类型/值是否同一命名空间无关,
29
+ * tsc 按导出名字符串判定冲突)。两处结论均以最小复现验证过,详见工单汇报。
30
+ */
31
+ const RunkoFS = {
32
+ fromMemory,
33
+ fromDirectory
34
+ };
35
+ //#endregion
36
+ //#region src/session.ts
37
+ /** 八件套的全部工具名,按 docs/tech/builtin-tools.md §1.1–§1.8 的声明顺序列出。 */
38
+ const ALL_FILE_TOOL_NAMES = [
39
+ "read-file",
40
+ "write-file",
41
+ "edit-file",
42
+ "delete-file",
43
+ "move-file",
44
+ "list-dir",
45
+ "glob",
46
+ "grep"
47
+ ];
48
+ /**
49
+ * `agent.builtinTools` 对文件工具八件套的过滤(docs/tech/builtin-tools.md §3):
50
+ * `false` 全关;`undefined`(未配置)默认全开;数组按白名单交集(数组里
51
+ * 出现的 `update-plan`/其他非文件工具名对这里无意义,交集自然把它们滤掉——
52
+ * `update-plan` 的开关逻辑仍由 core 自己的 `isUpdatePlanEnabled` 负责,两条
53
+ * 过滤各自独立、互不影响)。
54
+ */
55
+ function resolveEnabledFileToolNames(builtinTools) {
56
+ if (builtinTools === false) return [];
57
+ if (builtinTools === void 0) return ALL_FILE_TOOL_NAMES;
58
+ const requested = new Set(builtinTools);
59
+ return ALL_FILE_TOOL_NAMES.filter((name) => requested.has(name));
60
+ }
61
+ /**
62
+ * 预构造 `readState`/`derivedData` store 并拼出过滤后的文件工具八件套——
63
+ * 沿用 core `session.ts` 文件头记录的宿主装配姿态(`createFileTools({ readState,
64
+ * onFileChange })`,`onFileChange` 把 `FileChange[]` 逐条转发进
65
+ * `derivedData.recordFileChange`),只是这里由 sdk 在 `createSession(...)` 内部
66
+ * 自动完成,宿主不需要再手写这段拼装(P4-2 集成测试里手写的那段,正是这里的
67
+ * 落地位置)。
68
+ */
69
+ function buildDefaultFileTools(agent, readState, derivedData) {
70
+ const enabledNames = resolveEnabledFileToolNames(agent.builtinTools);
71
+ if (enabledNames.length === 0) return {};
72
+ const allFileTools = createFileTools({
73
+ readState,
74
+ onFileChange: (changes) => {
75
+ for (const change of changes) derivedData.recordFileChange(change);
76
+ }
77
+ });
78
+ const enabled = {};
79
+ for (const name of enabledNames) enabled[name] = allFileTools[name];
80
+ return enabled;
81
+ }
82
+ /** `fs`/`workspace` 都未提供时才注入默认 `MemoryFS`——两者任一存在都原样透传给 core 自行解析(含互斥校验与 exec 派生)。 */
83
+ function withDefaultFs(opts) {
84
+ if (opts.fs !== void 0 || opts.workspace !== void 0) return opts;
85
+ return {
86
+ ...opts,
87
+ fs: new MemoryFS()
88
+ };
89
+ }
90
+ function createSession(agent, opts = {}) {
91
+ const readState = opts.readState ?? createSessionReadState();
92
+ const derivedData = opts.derivedData ?? createDerivedDataCollector();
93
+ const tools = {
94
+ ...buildDefaultFileTools(agent, readState, derivedData),
95
+ ...agent.tools ?? {}
96
+ };
97
+ return createSession$1({
98
+ ...agent,
99
+ tools
100
+ }, withDefaultFs({
101
+ ...opts,
102
+ readState,
103
+ derivedData
104
+ }));
105
+ }
106
+ //#endregion
107
+ export { RunkoFS, createSession };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@runko/sdk",
3
+ "version": "0.1.0",
4
+ "description": "runko 主包(门面):re-export core + virtual-fs(+ mini-bash),batteries-included",
5
+ "type": "module",
6
+ "license": "ISC",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "registry": "https://registry.npmjs.org/"
10
+ },
11
+ "engines": {
12
+ "node": ">=24"
13
+ },
14
+ "main": "./dist/index.cjs",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "import": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ },
23
+ "require": {
24
+ "types": "./dist/index.d.cts",
25
+ "default": "./dist/index.cjs"
26
+ }
27
+ },
28
+ "./package.json": "./package.json"
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "dependencies": {
34
+ "@runko/core": "^0.1.0",
35
+ "@runko/virtual-fs": "^0.1.0",
36
+ "@runko/mini-bash": "^0.1.0"
37
+ },
38
+ "peerDependencies": {
39
+ "ai": "^7"
40
+ },
41
+ "devDependencies": {
42
+ "@ai-sdk/deepseek": "^3.0.7",
43
+ "@types/node": "^24.13.3",
44
+ "ai": "^7.0.20",
45
+ "tsdown": "^0.22.4",
46
+ "typescript": "^7.0.2",
47
+ "vitest": "^4.1.10",
48
+ "zod": "^4.4.3"
49
+ },
50
+ "scripts": {
51
+ "build": "tsdown",
52
+ "typecheck": "tsc --noEmit",
53
+ "lint": "eslint . --report-unused-disable-directives --max-warnings 0",
54
+ "lint:fix": "eslint . --fix",
55
+ "test": "vitest run"
56
+ }
57
+ }