@struktoai/mirage-dsh 0.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cordis.patch.yml +54 -0
- package/dist/chunk-C67TSSYB.js +392 -0
- package/dist/chunk-C67TSSYB.js.map +1 -0
- package/dist/chunk-CATVBGGR.js +70 -0
- package/dist/chunk-CATVBGGR.js.map +1 -0
- package/dist/chunk-J6F4OX6Z.js +102 -0
- package/dist/chunk-J6F4OX6Z.js.map +1 -0
- package/dist/chunk-ZSZVHBSL.js +455 -0
- package/dist/chunk-ZSZVHBSL.js.map +1 -0
- package/dist/fs-CuiUEA7A.d.ts +54 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin/fs.d.ts +3 -0
- package/dist/plugin/fs.js +8 -0
- package/dist/plugin/fs.js.map +1 -0
- package/dist/plugin/service.d.ts +4 -0
- package/dist/plugin/service.js +7 -0
- package/dist/plugin/service.js.map +1 -0
- package/dist/plugin/shell.d.ts +3 -0
- package/dist/plugin/shell.js +8 -0
- package/dist/plugin/shell.js.map +1 -0
- package/dist/service-CxFYAvoV.d.ts +91 -0
- package/dist/shell-B0N_jppN.d.ts +108 -0
- package/package.json +71 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { FileSystem, FsTarget, FsInfo, FsPathInfo, FsDirEntry, FsWriteIntent, FsWriteOutcome, FsEditRequest, FsVersion, FsEditOutcome } from '@deepseek-ai/dsh-fs';
|
|
3
|
+
|
|
4
|
+
/** Configuration for the mirage filesystem backend. */
|
|
5
|
+
interface MirageFsConfig {
|
|
6
|
+
/** Virtual base directory for relative paths. Defaults to `/`. */
|
|
7
|
+
cwd?: string;
|
|
8
|
+
/** Exclusive byte limit on each overwrite-diff side. Defaults to 10 MiB. */
|
|
9
|
+
diffBasisMaxBytes?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Mirage-backed implementation of `ctx.fs`. Targets are canonical virtual
|
|
13
|
+
* paths (namespace symlinks followed), every operation walks the workspace
|
|
14
|
+
* op door — session grants, admission policies, cache read-through and
|
|
15
|
+
* post-write invalidation all fire exactly as they do for a shell command —
|
|
16
|
+
* and `processPath` answers in the same virtual path space the mirage shell
|
|
17
|
+
* executes in, so the two providers share one execution world.
|
|
18
|
+
*/
|
|
19
|
+
declare class MirageFileSystem extends FileSystem {
|
|
20
|
+
static readonly inject: string[];
|
|
21
|
+
private fsOps;
|
|
22
|
+
private readonly cwd;
|
|
23
|
+
private readonly diffBasisMaxBytes;
|
|
24
|
+
private readonly locks;
|
|
25
|
+
constructor(ctx: Context, config?: MirageFsConfig);
|
|
26
|
+
private ops;
|
|
27
|
+
private get links();
|
|
28
|
+
private normalize;
|
|
29
|
+
private follow;
|
|
30
|
+
private withLock;
|
|
31
|
+
resolve(path: string, opts?: {
|
|
32
|
+
cwd?: string;
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
}): Promise<FsTarget>;
|
|
35
|
+
processPath(target: FsTarget): string;
|
|
36
|
+
fileUrl(target: FsTarget): string;
|
|
37
|
+
contains(parent: FsTarget, child: FsTarget): boolean;
|
|
38
|
+
stat(target: FsTarget, signal?: AbortSignal): Promise<FsInfo | undefined>;
|
|
39
|
+
lstat(path: string, opts?: {
|
|
40
|
+
cwd?: string;
|
|
41
|
+
}, signal?: AbortSignal): Promise<FsPathInfo | undefined>;
|
|
42
|
+
readText(target: FsTarget, signal?: AbortSignal): Promise<string>;
|
|
43
|
+
streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>;
|
|
44
|
+
listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>;
|
|
45
|
+
private dirEntry;
|
|
46
|
+
writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>;
|
|
47
|
+
private diffBasis;
|
|
48
|
+
private versionAfterWrite;
|
|
49
|
+
editText(target: FsTarget, edit: FsEditRequest, expected?: {
|
|
50
|
+
version: FsVersion;
|
|
51
|
+
}, signal?: AbortSignal): Promise<FsEditOutcome>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { MirageFileSystem as M, type MirageFsConfig as a };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { M as MirageConfig, a as MirageMount, b as MirageMountBlock, c as MirageRuntimeBlock, d as MirageService } from './service-CxFYAvoV.js';
|
|
2
|
+
export { M as MirageFileSystem, a as MirageFsConfig } from './fs-CuiUEA7A.js';
|
|
3
|
+
export { M as MirageShellConfig, a as MirageShellExecutor } from './shell-B0N_jppN.js';
|
|
4
|
+
import '@deepseek-ai/cordis';
|
|
5
|
+
import '@struktoai/mirage-core';
|
|
6
|
+
import '@struktoai/mirage-node';
|
|
7
|
+
import '@deepseek-ai/dsh-fs';
|
|
8
|
+
import '@deepseek-ai/dsh-shell';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MirageFileSystem
|
|
3
|
+
} from "./chunk-C67TSSYB.js";
|
|
4
|
+
import {
|
|
5
|
+
MirageService
|
|
6
|
+
} from "./chunk-J6F4OX6Z.js";
|
|
7
|
+
import {
|
|
8
|
+
MirageShellExecutor
|
|
9
|
+
} from "./chunk-ZSZVHBSL.js";
|
|
10
|
+
import "./chunk-CATVBGGR.js";
|
|
11
|
+
export {
|
|
12
|
+
MirageFileSystem,
|
|
13
|
+
MirageService,
|
|
14
|
+
MirageShellExecutor
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Service, Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { MountSpec } from '@struktoai/mirage-core';
|
|
3
|
+
import { Workspace, Mount, NodeWorkspaceOptions } from '@struktoai/mirage-node';
|
|
4
|
+
|
|
5
|
+
declare module '@deepseek-ai/cordis' {
|
|
6
|
+
interface Context {
|
|
7
|
+
mirage: MirageService;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A declarative mount, YAML-friendly: the resource is named by its
|
|
12
|
+
* registry type and built through `buildResource`, so a dsh bundle
|
|
13
|
+
* patch can mount anything without holding a live instance. Told apart
|
|
14
|
+
* from a live `Mount` by the type of `resource`: a string names a
|
|
15
|
+
* registry entry, an object is the instance itself.
|
|
16
|
+
*/
|
|
17
|
+
interface MirageMountBlock {
|
|
18
|
+
/** Resource registry name (`ram`, `s3`, `slack`, `redis`, ...). */
|
|
19
|
+
resource: string;
|
|
20
|
+
/** Mount mode: `read`, `write`, or `exec`. Omitted = the workspace default. */
|
|
21
|
+
mode?: string;
|
|
22
|
+
/** Resource constructor config, passed to the registry factory. */
|
|
23
|
+
config?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/** One mount entry: a live spec or instance, or a declarative block. */
|
|
26
|
+
type MirageMount = MountSpec | Mount | MirageMountBlock;
|
|
27
|
+
/** A runtime entry, YAML-friendly: a name, or a name with captures. */
|
|
28
|
+
interface MirageRuntimeBlock {
|
|
29
|
+
/** Runtime registry name (`monty`, `pyodide`, `quickjs`, ...). */
|
|
30
|
+
name: string;
|
|
31
|
+
/** Command words this runtime captures (e.g. `['python', 'python3']`). */
|
|
32
|
+
captures?: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Configuration for the shared mirage execution world. Exactly one of
|
|
36
|
+
* `workspace` (adopt a live workspace the embedder owns and closes) or
|
|
37
|
+
* `mounts` (construct a workspace here; the service closes it when its
|
|
38
|
+
* plugin unloads) must be given.
|
|
39
|
+
*/
|
|
40
|
+
interface MirageConfig {
|
|
41
|
+
/** A live workspace to adopt; its lifecycle stays with the embedder. */
|
|
42
|
+
workspace?: Workspace;
|
|
43
|
+
/** Mounts for a service-owned workspace, keyed by mount prefix. */
|
|
44
|
+
mounts?: Record<string, MirageMount>;
|
|
45
|
+
/**
|
|
46
|
+
* Runtimes for a service-owned workspace, built via `buildRuntime`.
|
|
47
|
+
* The YAML-friendly twin of `workspaceOptions.runtimes`; pass one or
|
|
48
|
+
* the other, not both.
|
|
49
|
+
*/
|
|
50
|
+
runtimes?: (string | MirageRuntimeBlock)[];
|
|
51
|
+
/** Options forwarded to the service-owned workspace's constructor. */
|
|
52
|
+
workspaceOptions?: NodeWorkspaceOptions;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The one mirage `Workspace` behind every mirage-backed dsh provider
|
|
56
|
+
* (`ctx.mirage`, mirroring how `ctx.e2b` owns one sandbox for the E2B
|
|
57
|
+
* adapters). `MirageFileSystem` and `MirageShellExecutor` both inject it,
|
|
58
|
+
* which is what keeps `ctx.fs` targets and `ctx.shell` commands in one
|
|
59
|
+
* execution world: a `processPath` handed to the shell resolves there.
|
|
60
|
+
*
|
|
61
|
+
* Construction with live resources is synchronous; a declarative mount
|
|
62
|
+
* block defers to `buildResource`, so consumers await `ready` (the
|
|
63
|
+
* adapters do) and `workspace` throws until it resolves, mirroring how
|
|
64
|
+
* the E2B service owner exposes its sandbox.
|
|
65
|
+
*/
|
|
66
|
+
declare class MirageService extends Service {
|
|
67
|
+
static readonly provide = "mirage";
|
|
68
|
+
/** Resolves to the shared workspace once every mount is built. */
|
|
69
|
+
readonly ready: Promise<Workspace>;
|
|
70
|
+
private built;
|
|
71
|
+
private readonly plannedRuntimes;
|
|
72
|
+
constructor(ctx: Context, config?: MirageConfig);
|
|
73
|
+
/** The live workspace; throws until `ready` resolves. */
|
|
74
|
+
get workspace(): Workspace;
|
|
75
|
+
/**
|
|
76
|
+
* True while every runtime in the world reaches only the vfs
|
|
77
|
+
* (`Runtime.reach`), meaning the workspace dispatch is the single
|
|
78
|
+
* gate for anything the agent can execute: every effect passes
|
|
79
|
+
* mount modes, session grants, and policy before touching the real
|
|
80
|
+
* backend behind a mount. The default world qualifies, and so do
|
|
81
|
+
* the bridged engines, while the host `local` python or a remote
|
|
82
|
+
* sandbox can act around the gate. Answers before `ready` from the
|
|
83
|
+
* constructor-resolved entries (mounts resolve asynchronously,
|
|
84
|
+
* runtimes never do) and from the live workspace afterwards, so a
|
|
85
|
+
* later `addRuntime` is seen.
|
|
86
|
+
*/
|
|
87
|
+
get vfsOnly(): boolean;
|
|
88
|
+
private open;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { type MirageConfig as M, type MirageMount as a, type MirageMountBlock as b, type MirageRuntimeBlock as c, MirageService as d };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { ShellExecutor, ShellExecRequest, ShellExecSpec, ShellRunResult, ShellProcess } from '@deepseek-ai/dsh-shell';
|
|
3
|
+
|
|
4
|
+
/** Configuration for the mirage shell executor. */
|
|
5
|
+
interface MirageShellConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Default working directory for commands. Defaults to `/`. With
|
|
8
|
+
* `sessionId` it instead seeds the bound session's initial cwd, and the
|
|
9
|
+
* session's own cwd is the default from then on.
|
|
10
|
+
*/
|
|
11
|
+
workdir?: string;
|
|
12
|
+
/** Default foreground timeout in milliseconds. Defaults to 120000. */
|
|
13
|
+
defaultTimeoutMs?: number;
|
|
14
|
+
/** Upper cap on any requested timeout. Defaults to 600000. */
|
|
15
|
+
maxTimeoutMs?: number;
|
|
16
|
+
/** Default stdout capture budget in bytes. Defaults to 200000. */
|
|
17
|
+
stdoutMaxBytes?: number;
|
|
18
|
+
/** stderr capture budget in bytes. Defaults to 64000. */
|
|
19
|
+
stderrMaxBytes?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Bind every command to this named workspace session. By default each
|
|
22
|
+
* command runs in an ephemeral fork of the workspace's default session,
|
|
23
|
+
* so nothing persists between calls, which is the one-shot contract of
|
|
24
|
+
* dsh's bash tool. With a session bound, `cd`, `export`, and function
|
|
25
|
+
* definitions persist across calls, the persistent-shell contract. The
|
|
26
|
+
* session is created on first use if the workspace does not have it; an
|
|
27
|
+
* existing session is adopted as is. A spec carrying an explicit
|
|
28
|
+
* `workdir` or `env` still runs as a one-call subshell of the bound
|
|
29
|
+
* session, per mirage's `ExecuteOptions` semantics.
|
|
30
|
+
*/
|
|
31
|
+
sessionId?: string;
|
|
32
|
+
/**
|
|
33
|
+
* When set, a background command whose streamed output overruns its
|
|
34
|
+
* delta budget spills its full stdout and stderr to files under this
|
|
35
|
+
* workspace directory, and `readOutput()` points at them so a reader
|
|
36
|
+
* can recover what the delta dropped. The directory is a workspace
|
|
37
|
+
* path (e.g. `/tmp` on a ram mount), so the agent reads the spill
|
|
38
|
+
* through the same VFS as everything else; the writes go through the
|
|
39
|
+
* workspace, so they appear in history like any other write. Unset
|
|
40
|
+
* (the default) means no spill: output that overruns is simply
|
|
41
|
+
* flagged `lossy`, the honest "no safe path available" answer.
|
|
42
|
+
*/
|
|
43
|
+
spillDir?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Mirage-backed implementation of `ctx.shell`: `run` executes the command
|
|
47
|
+
* line with mirage's own shell (coreutils-faithful commands, installed
|
|
48
|
+
* CLIs, the policy layer) against the shared `ctx.mirage` workspace, so a
|
|
49
|
+
* path from `ctx.fs` means the same file here. There is no OS process
|
|
50
|
+
* behind a command: `signal` in results is a compatibility value for kills,
|
|
51
|
+
* and abort/timeout act cooperatively at the executor's own boundaries.
|
|
52
|
+
*
|
|
53
|
+
* Every command runs in an ephemeral fork of the workspace's default
|
|
54
|
+
* session, so no shell state survives from one call to the next, matching
|
|
55
|
+
* the one-shot contract of dsh's bash tool. Configuring a `sessionId`
|
|
56
|
+
* binds all commands to one named session instead, whose cwd, exports,
|
|
57
|
+
* and functions persist across calls.
|
|
58
|
+
*/
|
|
59
|
+
declare class MirageShellExecutor extends ShellExecutor {
|
|
60
|
+
static readonly inject: string[];
|
|
61
|
+
private readonly workdir;
|
|
62
|
+
private readonly defaultTimeoutMs;
|
|
63
|
+
private readonly maxTimeoutMs;
|
|
64
|
+
private readonly stdoutMaxBytes;
|
|
65
|
+
private readonly stderrMaxBytes;
|
|
66
|
+
private readonly sessionId;
|
|
67
|
+
private readonly spillDir;
|
|
68
|
+
private sessionReady;
|
|
69
|
+
constructor(ctx: Context, config?: MirageShellConfig);
|
|
70
|
+
private workspace;
|
|
71
|
+
private newSpill;
|
|
72
|
+
/**
|
|
73
|
+
* With every runtime in the world reaching only the vfs
|
|
74
|
+
* (`ctx.mirage.vfsOnly`), the workspace dispatch is the single gate
|
|
75
|
+
* for anything a command can do, so this executor behaves like a
|
|
76
|
+
* workspace-write sandbox: reads and writes land only where mounts
|
|
77
|
+
* (and their modes) allow. Declaring it lets sandbox-aware plugins
|
|
78
|
+
* (dsh's permission presets) compose over this executor. A world
|
|
79
|
+
* holding a runtime with doors around the gate (the host `local`
|
|
80
|
+
* python, a remote sandbox) voids that claim, so this answers
|
|
81
|
+
* undefined then (the base contract's "does not sandbox") and those
|
|
82
|
+
* plugins refuse to compose instead of trusting a lie.
|
|
83
|
+
*/
|
|
84
|
+
get sandboxMode(): ShellExecutor['sandboxMode'];
|
|
85
|
+
/**
|
|
86
|
+
* The sandbox facts to stamp on this run's result and process handle,
|
|
87
|
+
* or undefined when the world is not fully workspace-bound (no claim).
|
|
88
|
+
*
|
|
89
|
+
* `enforcement` is 'full': when every runtime reaches only the vfs, the
|
|
90
|
+
* workspace gate cannot be bypassed, so unlike an OS sandbox on an older
|
|
91
|
+
* kernel there is no promised effect it fails to govern. `denied` is
|
|
92
|
+
* false because mirage has no out-of-band denial channel: a refused write
|
|
93
|
+
* (a read-only mount) fails in-band as an ordinary command error with a
|
|
94
|
+
* nonzero exit, the way EROFS would, not as a separate sandbox verdict,
|
|
95
|
+
* so there is nothing here to distinguish from the command's own failure.
|
|
96
|
+
* `runnerFailed` is false because the workspace executor is the runner
|
|
97
|
+
* and a failure to run surfaces as a rejected/aborted execution, not a
|
|
98
|
+
* runner that never started.
|
|
99
|
+
*/
|
|
100
|
+
private sandboxInfo;
|
|
101
|
+
resolve(request: ShellExecRequest): ShellExecSpec;
|
|
102
|
+
private ensureSession;
|
|
103
|
+
private provisionSession;
|
|
104
|
+
run(spec: ShellExecSpec): Promise<ShellRunResult>;
|
|
105
|
+
start(spec: ShellExecSpec): ShellProcess;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { type MirageShellConfig as M, MirageShellExecutor as a };
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@struktoai/mirage-dsh",
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"description": "DeepSeek Harness (dsh) providers backed by a mirage workspace: ctx.fs and ctx.shell over mounted resources",
|
|
5
|
+
"homepage": "https://github.com/strukto-ai/mirage#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/strukto-ai/mirage/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/strukto-ai/mirage.git",
|
|
12
|
+
"directory": "typescript/packages/dsh"
|
|
13
|
+
},
|
|
14
|
+
"license": "Apache-2.0",
|
|
15
|
+
"author": "Zecheng Zhang <zecheng@strukto.ai>",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./service": {
|
|
28
|
+
"types": "./dist/plugin/service.d.ts",
|
|
29
|
+
"import": "./dist/plugin/service.js"
|
|
30
|
+
},
|
|
31
|
+
"./fs": {
|
|
32
|
+
"types": "./dist/plugin/fs.d.ts",
|
|
33
|
+
"import": "./dist/plugin/fs.js"
|
|
34
|
+
},
|
|
35
|
+
"./shell": {
|
|
36
|
+
"types": "./dist/plugin/shell.d.ts",
|
|
37
|
+
"import": "./dist/plugin/shell.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"dsh": {
|
|
41
|
+
"bundle": {
|
|
42
|
+
"patch": "./cordis.patch.yml"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"cordis.patch.yml"
|
|
48
|
+
],
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@struktoai/mirage-node": "0.0.5-alpha.1",
|
|
51
|
+
"@struktoai/mirage-core": "0.0.5-alpha.1"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
55
|
+
"@deepseek-ai/dsh-fs": "0.0.1-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-shell": "0.0.1-rc.5"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
60
|
+
"@deepseek-ai/dsh-fs": "0.0.1-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-shell": "0.0.1-rc.5",
|
|
62
|
+
"tsup": "^8.5.0",
|
|
63
|
+
"typescript": "^6.0.0",
|
|
64
|
+
"vitest": "^3.2.6"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsup",
|
|
68
|
+
"test": "vitest run",
|
|
69
|
+
"typecheck": "tsc --noEmit"
|
|
70
|
+
}
|
|
71
|
+
}
|