@codeworksh/plugin 0.1.0-canary.17.1.g648af395 → 0.1.0-canary.18.1.g00a873ad

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.
@@ -156,14 +156,19 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
156
156
  type: "image";
157
157
  data: string;
158
158
  mimeType: string;
159
+ } | {
160
+ type: "thinking";
161
+ thinking: string;
162
+ thinkingSignature?: string;
163
+ redacted?: boolean;
159
164
  } | {
160
165
  addedToolNames?: string[];
161
166
  arguments: Record<string, any>;
162
167
  callID: string;
163
168
  name: string;
164
169
  namespace?: string;
165
- result: {
166
- content: ({
170
+ partial?: {
171
+ content?: ({
167
172
  type: "text";
168
173
  text: string;
169
174
  textSignature?: string;
@@ -173,9 +178,8 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
173
178
  mimeType: string;
174
179
  })[];
175
180
  details?: any;
176
- isError: false;
177
181
  };
178
- status: "completed";
182
+ status: "running";
179
183
  thoughtSignature?: string;
180
184
  time: {
181
185
  start: number;
@@ -199,9 +203,9 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
199
203
  mimeType: string;
200
204
  })[];
201
205
  details?: any;
202
- isError: true;
206
+ isError: false;
203
207
  };
204
- status: "error";
208
+ status: "completed";
205
209
  thoughtSignature?: string;
206
210
  time: {
207
211
  start: number;
@@ -227,7 +231,7 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
227
231
  details?: any;
228
232
  isError: true;
229
233
  };
230
- status: "skipped";
234
+ status: "error";
231
235
  thoughtSignature?: string;
232
236
  time: {
233
237
  start: number;
@@ -253,26 +257,21 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
253
257
  details?: any;
254
258
  isError: true;
255
259
  };
256
- status: "aborted";
260
+ status: "skipped";
257
261
  thoughtSignature?: string;
258
262
  time: {
259
263
  start: number;
260
264
  end: number;
261
265
  };
262
266
  type: "toolCall";
263
- } | {
264
- type: "thinking";
265
- thinking: string;
266
- thinkingSignature?: string;
267
- redacted?: boolean;
268
267
  } | {
269
268
  addedToolNames?: string[];
270
269
  arguments: Record<string, any>;
271
270
  callID: string;
272
271
  name: string;
273
272
  namespace?: string;
274
- partial?: {
275
- content?: ({
273
+ result: {
274
+ content: ({
276
275
  type: "text";
277
276
  text: string;
278
277
  textSignature?: string;
@@ -282,8 +281,9 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
282
281
  mimeType: string;
283
282
  })[];
284
283
  details?: any;
284
+ isError: true;
285
285
  };
286
- status: "running";
286
+ status: "aborted";
287
287
  thoughtSignature?: string;
288
288
  time: {
289
289
  start: number;
@@ -458,14 +458,19 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
458
458
  type: "image";
459
459
  data: string;
460
460
  mimeType: string;
461
+ } | {
462
+ type: "thinking";
463
+ thinking: string;
464
+ thinkingSignature?: string;
465
+ redacted?: boolean;
461
466
  } | {
462
467
  addedToolNames?: string[];
463
468
  arguments: Record<string, any>;
464
469
  callID: string;
465
470
  name: string;
466
471
  namespace?: string;
467
- result: {
468
- content: ({
472
+ partial?: {
473
+ content?: ({
469
474
  type: "text";
470
475
  text: string;
471
476
  textSignature?: string;
@@ -475,9 +480,8 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
475
480
  mimeType: string;
476
481
  })[];
477
482
  details?: any;
478
- isError: false;
479
483
  };
480
- status: "completed";
484
+ status: "running";
481
485
  thoughtSignature?: string;
482
486
  time: {
483
487
  start: number;
@@ -501,9 +505,9 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
501
505
  mimeType: string;
502
506
  })[];
503
507
  details?: any;
504
- isError: true;
508
+ isError: false;
505
509
  };
506
- status: "error";
510
+ status: "completed";
507
511
  thoughtSignature?: string;
508
512
  time: {
509
513
  start: number;
@@ -529,7 +533,7 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
529
533
  details?: any;
530
534
  isError: true;
531
535
  };
532
- status: "skipped";
536
+ status: "error";
533
537
  thoughtSignature?: string;
534
538
  time: {
535
539
  start: number;
@@ -555,26 +559,21 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
555
559
  details?: any;
556
560
  isError: true;
557
561
  };
558
- status: "aborted";
562
+ status: "skipped";
559
563
  thoughtSignature?: string;
560
564
  time: {
561
565
  start: number;
562
566
  end: number;
563
567
  };
564
568
  type: "toolCall";
565
- } | {
566
- type: "thinking";
567
- thinking: string;
568
- thinkingSignature?: string;
569
- redacted?: boolean;
570
569
  } | {
571
570
  addedToolNames?: string[];
572
571
  arguments: Record<string, any>;
573
572
  callID: string;
574
573
  name: string;
575
574
  namespace?: string;
576
- partial?: {
577
- content?: ({
575
+ result: {
576
+ content: ({
578
577
  type: "text";
579
578
  text: string;
580
579
  textSignature?: string;
@@ -584,8 +583,9 @@ declare const AikitAssistantMessage: Schema.decodeTo<Schema.declare<{
584
583
  mimeType: string;
585
584
  })[];
586
585
  details?: any;
586
+ isError: true;
587
587
  };
588
- status: "running";
588
+ status: "aborted";
589
589
  thoughtSignature?: string;
590
590
  time: {
591
591
  start: number;
@@ -896,4 +896,4 @@ declare function durable<const Definitions extends ReadonlyArray<Definition>>(de
896
896
  declare function latest(definitions: ReadonlyArray<Definition>): ReadonlyMap<string, Definition<string, Schema.Codec<unknown, unknown, never, never>>>;
897
897
  //#endregion
898
898
  export { ID as a, define as c, inventory as d, latest as f, Definition as i, durable as l, AikitToolCallTerminalPart as n, Payload as o, versionedType as p, Data as r, PublishOptions as s, AikitAssistantMessage as t, event_d_exports as u };
899
- //# sourceMappingURL=event-mKxToqmh.d.mts.map
899
+ //# sourceMappingURL=event-6sTQ_4bq.d.mts.map
package/event.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as ID, c as define, d as inventory, f as latest, i as Definition, l as durable, n as AikitToolCallTerminalPart, o as Payload, p as versionedType, r as Data, s as PublishOptions, t as AikitAssistantMessage, u as event_d_exports } from "./event-mKxToqmh.mjs";
1
+ import { a as ID, c as define, d as inventory, f as latest, i as Definition, l as durable, n as AikitToolCallTerminalPart, o as Payload, p as versionedType, r as Data, s as PublishOptions, t as AikitAssistantMessage, u as event_d_exports } from "./event-6sTQ_4bq.mjs";
2
2
  export { AikitAssistantMessage, AikitToolCallTerminalPart, Data, Definition, event_d_exports as EventSchema, ID, Payload, PublishOptions, define, durable, inventory, latest, versionedType };
@@ -57,12 +57,14 @@ interface RmOptions {
57
57
  /** Whether a provider failure means the path itself is definitively absent. */
58
58
  declare const isNotFoundError: (cause: unknown) => boolean;
59
59
  /**
60
- * Shell forms of `realpath` for backends that only expose a process API.
61
- * `pwd -P` is the portable primitive: directories resolve directly, anything
62
- * else resolves its parent and keeps the final name as given. Run as
63
- * `sh -c <script> _ <path>`; try the first, fall back to the second.
60
+ * Shell forms of `realpath` for backends that only expose a process API. Run as
61
+ * `sh -c <script> _ <path>`, trying each in turn. `realpath -e` (coreutils)
62
+ * resolves every component, a symlinked file included, and fails on a missing
63
+ * path. Where it is absent, `pwd -P` is the portable primitive: directories
64
+ * resolve directly, anything else resolves its parent and keeps the final name
65
+ * as given — so a symlinked *file* stays unresolved there.
64
66
  */
65
- declare const realpathScripts: readonly ['cd -- "$1" && pwd -P', 'cd -- "$(dirname -- "$1")" && printf \'%s/%s\' "$(pwd -P)" "$(basename -- "$1")"'];
67
+ declare const realpathScripts: readonly ['realpath -e -- "$1"', 'cd -- "$1" && pwd -P', 'cd -- "$(dirname -- "$1")" && printf \'%s/%s\' "$(pwd -P)" "$(basename -- "$1")"'];
66
68
  /**
67
69
  * The backend-facing contract. Backends author plain promises and let them
68
70
  * reject; {@link fromProvider} turns rejections into typed failures.
@@ -139,4 +141,4 @@ declare const fromProvider: (provider: Provider) => Interface;
139
141
  declare const withCwd: (fs: Interface, cwd: string) => Interface;
140
142
  //#endregion
141
143
  export { Provider as a, filesystem_d_exports as c, realpathScripts as d, validateRmOptions as f, OperationUnsupportedError as i, fromProvider as l, FileSystemError as n, RmOptions as o, withCwd as p, Interface as r, Service as s, FileStat as t, isNotFoundError as u };
142
- //# sourceMappingURL=filesystem-Cp-KapCE.d.mts.map
144
+ //# sourceMappingURL=filesystem-Cv2gjOJa.d.mts.map
package/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { t as section_d_exports } from "./plugin/section.mjs";
2
2
  import { g as tool_d_exports } from "./tool-DuYBgiJf.mjs";
3
- import { t as plugin_d_exports } from "./plugin-DBrMUV15.mjs";
3
+ import { t as plugin_d_exports } from "./plugin-Bc2vSo2k.mjs";
4
4
  export { plugin_d_exports as Plugin, section_d_exports as Section, tool_d_exports as Tool };
@@ -0,0 +1,182 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { ID } from "./sandbox/instance.mjs";
3
+ import { posix } from "./posix.mjs";
4
+ import { Service as Service$1, isNotFoundError, withCwd } from "./sandbox/filesystem.mjs";
5
+ import { Shell as Shell$1, withCwd as withCwd$1 } from "./sandbox/shell.mjs";
6
+ import { Context, Deferred, Effect, Layer } from "effect";
7
+ //#region src/sandbox/mutation.ts
8
+ var Service = class extends Context.Service()("@codeworksh/plugin/sandbox/mutation/Service") {};
9
+ const locks = /* @__PURE__ */ new Map();
10
+ /** Hand the file to the next waiter, or free it. Ownership moves directly, so no newcomer can barge in. */
11
+ const release = (key, lock) => {
12
+ const next = lock.waiters.shift();
13
+ if (next === void 0) locks.delete(key);
14
+ else Deferred.doneUnsafe(next, Effect.void);
15
+ };
16
+ /** Take the file, waiting interruptibly; must run uninterruptibly so taking and releasing pair up. */
17
+ const acquire = (key, restore) => Effect.suspend(() => {
18
+ const lock = locks.get(key);
19
+ if (lock === void 0) {
20
+ locks.set(key, { waiters: [] });
21
+ return Effect.void;
22
+ }
23
+ const turn = Deferred.makeUnsafe();
24
+ lock.waiters.push(turn);
25
+ return restore(Deferred.await(turn)).pipe(Effect.onInterrupt(() => Effect.sync(() => {
26
+ const index = lock.waiters.indexOf(turn);
27
+ if (index !== -1) lock.waiters.splice(index, 1);
28
+ else release(key, lock);
29
+ })));
30
+ });
31
+ /**
32
+ * The canonical path. A file that does not exist yet takes its canonical
33
+ * parent joined with its name, walking up as far as needed, so a write that
34
+ * creates a file (and its directories) shares a key with later mutations of it.
35
+ */
36
+ const canonical = (fs, path) => fs.realpath(path).pipe(Effect.catchIf((error) => isNotFoundError(error.cause), (error) => {
37
+ const parent = posix.dirname(path);
38
+ if (parent === path) return Effect.fail(error);
39
+ return Effect.map(canonical(fs, parent), (resolved) => posix.join(resolved, posix.basename(path)));
40
+ }));
41
+ const make = (instance, cwd, fs) => ({ withFile: (path, effect) => Effect.flatMap(canonical(fs, posix.resolve(cwd, path)), (resolved) => {
42
+ const key = `${instance}\0${resolved}`;
43
+ return Effect.uninterruptibleMask((restore) => Effect.andThen(acquire(key, restore), restore(effect).pipe(Effect.ensuring(Effect.sync(() => {
44
+ const lock = locks.get(key);
45
+ if (lock !== void 0) release(key, lock);
46
+ })))));
47
+ }) });
48
+ //#endregion
49
+ //#region src/sandbox/io.ts
50
+ var io_exports = /* @__PURE__ */ __exportAll({
51
+ Current: () => Current,
52
+ FileSystem: () => FileSystem,
53
+ Mutation: () => Mutation,
54
+ SandboxIO: () => io_exports,
55
+ Shell: () => Shell,
56
+ host: () => host,
57
+ hostLayer: () => hostLayer,
58
+ identityLayer: () => identityLayer,
59
+ mount: () => mount,
60
+ remote: () => remote,
61
+ resolveMountCwd: () => resolveMountCwd,
62
+ virtual: () => virtual,
63
+ withMutation: () => withMutation
64
+ });
65
+ /**
66
+ * `SandboxIO` is a **mount**: a filesystem, a shell, and the identity and
67
+ * working directory they act on.
68
+ *
69
+ * It is the whole vocabulary a consumer needs. Project, Git, Copy, Location, and
70
+ * every tool ask for `SandboxIO.FileSystem`, `SandboxIO.Shell`, and
71
+ * `SandboxIO.Current` — never for a driver, an address, or a provider SDK — so
72
+ * a host directory, an in-memory VFS, and a remote microVM are interchangeable
73
+ * behind one contract.
74
+ *
75
+ * The mount neither creates nor destroys infrastructure. `SandboxInstance` is
76
+ * the durable namespace it acts on — a device, which exists whether or not
77
+ * anything has it mounted — and `Sandbox.Controller` is the only path that
78
+ * creates, stops, or destroys one.
79
+ */
80
+ /**
81
+ * The filesystem tag. Re-exported here so consumers import one namespace —
82
+ * Project, Git, Copy, and the runner ask for `SandboxIO.FileSystem`, never for
83
+ * the module that happens to define it. Code *inside* `sandbox/` keeps importing
84
+ * the tag directly, since `io.ts` is built on top of it.
85
+ */
86
+ const FileSystem = Service$1;
87
+ /** The shell tag. Re-exported here so consumers import one namespace. */
88
+ const Shell = Shell$1;
89
+ /** Per-file mutation ordering for this mount's instance. Re-exported here so consumers import one namespace. */
90
+ const Mutation = Service;
91
+ /** Identity and working directory of the current mount. */
92
+ var Current = class extends Context.Service()("@codeworksh/plugin/sandbox/io/Current") {};
93
+ /**
94
+ * Resolve a mount's cwd without consulting ambient process state.
95
+ *
96
+ * The default is supplied by the namespace adapter:
97
+ * provider metadata remotely, `/` for a virtual filesystem, and `process.cwd()` for the host adapter.
98
+ * An explicit absolute cwd replaces it; a relative cwd is resolved inside it. The
99
+ * result is therefore always the one concrete absolute path `Current` requires.
100
+ *
101
+ * A non-absolute default throws rather than failing typed. It is the one
102
+ * defect-level guard in this module, and deliberately so:
103
+ * Adapters reading a value from a provider call this inside their own error channel,
104
+ * where the throw becomes their typed failure (see `EnvDaytona.mountCwd`).
105
+ */
106
+ const resolveMountCwd = (defaultCwd, cwd) => {
107
+ if (!posix.isAbsolute(defaultCwd)) throw new TypeError(`Sandbox default cwd must be absolute: ${defaultCwd}`);
108
+ if (cwd === void 0) return posix.resolve(defaultCwd);
109
+ return posix.isAbsolute(cwd) ? posix.resolve(cwd) : posix.resolve(defaultCwd, cwd);
110
+ };
111
+ /**
112
+ * Complete a mount with its {@link Mutation} queue, derived from the mount's own
113
+ * identity and filesystem. Every layer that provides a mount goes through here,
114
+ * so mounts of one instance always meet in the same queue.
115
+ */
116
+ const withMutation = (layer) => Layer.provideMerge(Layer.effect(Mutation, Effect.gen(function* () {
117
+ const current = yield* Current;
118
+ return make(current.id, current.cwd, yield* Service$1);
119
+ })), layer);
120
+ /**
121
+ * Bind a cwd-neutral transport to one mount.
122
+ *
123
+ * The transport underneath is shared between
124
+ * mounts and stays rooted at the namespace root, and everything directory-shaped
125
+ * happens here, once per mount. Two mounts of one namespace at different working
126
+ * directories therefore coexist without seeing or moving each other's.
127
+ *
128
+ * It consumes the same two tags it provides — the transport is supplied by the
129
+ * layer this is composed over, not by itself.
130
+ */
131
+ const mount = (identity) => Layer.mergeAll(Layer.succeed(Current, identity), Layer.effect(Service$1, Effect.map(Service$1, (fs) => withCwd(fs, identity.cwd))), Layer.effect(Shell$1, Effect.map(Shell$1, (shell) => withCwd$1(shell, identity.cwd)))).pipe(withMutation);
132
+ /**
133
+ * Just the identity tag, with no filesystem or shell beneath it. For consumers
134
+ * assembled from stubs — a test that runs `Project` over a fake filesystem still
135
+ * needs to know which namespace it is in.
136
+ */
137
+ const identityLayer = (identity) => Layer.succeed(Current, identity);
138
+ /** The host identity alone. See {@link identityLayer}. */
139
+ const hostLayer = (cwd) => identityLayer(host(cwd));
140
+ /**
141
+ * The host, rooted at `cwd`. Always `SandboxInstance.ID.local`: the working
142
+ * directory selects where relative paths resolve, it does not make a second host
143
+ * namespace — two mounts rooted at different directories still agree on absolute
144
+ * paths.
145
+ *
146
+ * The host coordinate is explicit so a caller cannot accidentally substitute ambient process
147
+ * state for the application or session directory it owns.
148
+ */
149
+ const host = (cwd) => ({
150
+ id: ID.local,
151
+ driver: "local",
152
+ kind: "local",
153
+ cwd: resolveMountCwd(cwd)
154
+ });
155
+ /**
156
+ * A VFS-backed namespace. The id is minted per call unless one is named, because
157
+ * building one of these builds a fresh VFS: N unnamed calls are N distinct
158
+ * namespaces, none of which outlives the process. A file-backed store is the
159
+ * exception — its file is the state, so whoever knows the file supplies the id
160
+ * it was registered under.
161
+ */
162
+ const virtual = (input) => ({
163
+ id: input.id ?? ID.create(),
164
+ driver: input.driver,
165
+ kind: "virtual",
166
+ cwd: resolveMountCwd(input.defaultCwd ?? "/", input.cwd)
167
+ });
168
+ /**
169
+ * A provider-hosted namespace. The id is always supplied: a remote resource's
170
+ * durable identity is minted and recorded by whoever provisioned it, never
171
+ * derived here from the provider's own locator.
172
+ */
173
+ const remote = (input) => ({
174
+ id: input.id,
175
+ driver: input.driver,
176
+ kind: "remote",
177
+ cwd: resolveMountCwd(input.defaultCwd, input.cwd)
178
+ });
179
+ //#endregion
180
+ export { host as a, io_exports as c, resolveMountCwd as d, virtual as f, Shell as i, mount as l, FileSystem as n, hostLayer as o, withMutation as p, Mutation as r, identityLayer as s, Current as t, remote as u };
181
+
182
+ //# sourceMappingURL=io-5PrgzDTe.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io-5PrgzDTe.mjs","names":["SandboxFileSystem.Service","ShellTag","SandboxMutation.Service","EffectLayer","SandboxMutation.make","SandboxFileSystem.withCwd","shellWithCwd"],"sources":["../../src/sandbox/mutation.ts","../../src/sandbox/io.ts"],"sourcesContent":["import { Context, Deferred, Effect } from \"effect\";\nimport { posix } from \"../posix.ts\";\nimport { type FileSystemError, type Interface as FileSystem, isNotFoundError } from \"./filesystem.ts\";\nimport type { SandboxInstance } from \"./instance.ts\";\n\n/**\n * Serializes mutations of one file.\n *\n * Tool calls may run in parallel, and a file-mutating tool does read → modify →\n * write. Two of those on one file interleave and the first write is lost, so a\n * tool holds the file for its whole read-modify-write.\n *\n * A file is its sandbox instance plus its canonical path: two mounts of one\n * instance share files, and a symlinked spelling of a path is the same file.\n * Other files never wait. This orders the harness's own tools within this\n * process only; it is not a lock against `bash` or other processes.\n */\nexport interface Interface {\n\t/**\n\t * Run `effect` as the only mutation of `path` in flight. Calls queue in the\n\t * order their paths resolve, which for one spelling is the order they were made.\n\t */\n\treadonly withFile: <A, E, R>(\n\t\tpath: string,\n\t\teffect: Effect.Effect<A, E, R>,\n\t) => Effect.Effect<A, E | FileSystemError, R>;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\"@codeworksh/plugin/sandbox/mutation/Service\") {}\n\ninterface Lock {\n\treadonly waiters: Array<Deferred.Deferred<void>>;\n}\n\n// Process-wide on purpose: every mount of one instance must meet in the same\n// queue, whichever layer built it. A key is present exactly while its file is held.\nconst locks = new Map<string, Lock>();\n\n/** Hand the file to the next waiter, or free it. Ownership moves directly, so no newcomer can barge in. */\nconst release = (key: string, lock: Lock): void => {\n\tconst next = lock.waiters.shift();\n\tif (next === undefined) locks.delete(key);\n\telse Deferred.doneUnsafe(next, Effect.void);\n};\n\n/** Take the file, waiting interruptibly; must run uninterruptibly so taking and releasing pair up. */\nconst acquire = (key: string, restore: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>) =>\n\tEffect.suspend(() => {\n\t\tconst lock = locks.get(key);\n\t\tif (lock === undefined) {\n\t\t\tlocks.set(key, { waiters: [] });\n\t\t\treturn Effect.void;\n\t\t}\n\t\tconst turn = Deferred.makeUnsafe<void>();\n\t\tlock.waiters.push(turn);\n\t\treturn restore(Deferred.await(turn)).pipe(\n\t\t\tEffect.onInterrupt(() =>\n\t\t\t\tEffect.sync(() => {\n\t\t\t\t\tconst index = lock.waiters.indexOf(turn);\n\t\t\t\t\t// Still queued: leave. Already handed the file: pass it on.\n\t\t\t\t\tif (index !== -1) lock.waiters.splice(index, 1);\n\t\t\t\t\telse release(key, lock);\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t});\n\n/**\n * The canonical path. A file that does not exist yet takes its canonical\n * parent joined with its name, walking up as far as needed, so a write that\n * creates a file (and its directories) shares a key with later mutations of it.\n */\nconst canonical = (fs: FileSystem, path: string): Effect.Effect<string, FileSystemError> =>\n\tfs.realpath(path).pipe(\n\t\tEffect.catchIf(\n\t\t\t(error) => isNotFoundError(error.cause),\n\t\t\t(error) => {\n\t\t\t\tconst parent = posix.dirname(path);\n\t\t\t\tif (parent === path) return Effect.fail(error);\n\t\t\t\treturn Effect.map(canonical(fs, parent), (resolved) => posix.join(resolved, posix.basename(path)));\n\t\t\t},\n\t\t),\n\t);\n\nexport const make = (instance: SandboxInstance.ID, cwd: string, fs: FileSystem): Interface => ({\n\twithFile: (path, effect) =>\n\t\tEffect.flatMap(canonical(fs, posix.resolve(cwd, path)), (resolved) => {\n\t\t\tconst key = `${instance}\\0${resolved}`;\n\t\t\t// Held from the moment `acquire` returns: nothing can interrupt between\n\t\t\t// taking the file and installing its release.\n\t\t\treturn Effect.uninterruptibleMask((restore) =>\n\t\t\t\tEffect.andThen(\n\t\t\t\t\tacquire(key, restore),\n\t\t\t\t\trestore(effect).pipe(\n\t\t\t\t\t\tEffect.ensuring(\n\t\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\t\tconst lock = locks.get(key);\n\t\t\t\t\t\t\t\tif (lock !== undefined) release(key, lock);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}),\n});\n\nexport * as SandboxMutation from \"./mutation.ts\";\n","import { Context, Effect, Layer as EffectLayer } from \"effect\";\nimport { posix } from \"../posix.ts\";\nimport type { SandboxDriver } from \"./driver.ts\";\nimport { SandboxFileSystem } from \"./filesystem.ts\";\nimport { SandboxInstance } from \"./instance.ts\";\nimport { SandboxMutation } from \"./mutation.ts\";\nimport { type ISandboxExe, Shell as ShellTag, withCwd as shellWithCwd } from \"./shell.ts\";\n\n/**\n * `SandboxIO` is a **mount**: a filesystem, a shell, and the identity and\n * working directory they act on.\n *\n * It is the whole vocabulary a consumer needs. Project, Git, Copy, Location, and\n * every tool ask for `SandboxIO.FileSystem`, `SandboxIO.Shell`, and\n * `SandboxIO.Current` — never for a driver, an address, or a provider SDK — so\n * a host directory, an in-memory VFS, and a remote microVM are interchangeable\n * behind one contract.\n *\n * The mount neither creates nor destroys infrastructure. `SandboxInstance` is\n * the durable namespace it acts on — a device, which exists whether or not\n * anything has it mounted — and `Sandbox.Controller` is the only path that\n * creates, stops, or destroys one.\n */\n\n/**\n * The filesystem tag. Re-exported here so consumers import one namespace —\n * Project, Git, Copy, and the runner ask for `SandboxIO.FileSystem`, never for\n * the module that happens to define it. Code *inside* `sandbox/` keeps importing\n * the tag directly, since `io.ts` is built on top of it.\n */\nexport const FileSystem = SandboxFileSystem.Service;\nexport type FileSystem = SandboxFileSystem.Service;\n\n/** The shell tag. Re-exported here so consumers import one namespace. */\nexport const Shell = ShellTag;\nexport type Shell = ShellTag;\n\n/** Per-file mutation ordering for this mount's instance. Re-exported here so consumers import one namespace. */\nexport const Mutation = SandboxMutation.Service;\nexport type Mutation = SandboxMutation.Service;\n\n/**\n * What a mount sees: immutable identity, plus the working directory resolved for\n * *this* mount.\n *\n * Nothing mutable belongs here. `status`, `usage`, and reference counts all\n * change while a mount is open, so a mount-time snapshot of them would be wrong\n * by construction — runtime code that needs live management state asks the\n * control plane. The driver's own resource locator is likewise absent: consumers\n * never parse a Vercel name or a Daytona id.\n */\nexport interface Identity {\n\treadonly id: SandboxInstance.ID;\n\treadonly driver: SandboxDriver.Name;\n\treadonly kind: SandboxInstance.Kind;\n\t/** Absolute, and always a path in *this* namespace. */\n\treadonly cwd: string;\n}\n\n/** Identity and working directory of the current mount. */\nexport class Current extends Context.Service<Current, Identity>()(\"@codeworksh/plugin/sandbox/io/Current\") {}\n\n/** Everything a mount provides. */\nexport type Provides = Current | SandboxFileSystem.Service | ShellTag | SandboxMutation.Service;\n\n/** A built mount. */\nexport type Layer<E = never, RIn = never> = EffectLayer.Layer<Provides, E, RIn>;\n\n/**\n * Resolve a mount's cwd without consulting ambient process state.\n *\n * The default is supplied by the namespace adapter:\n * provider metadata remotely, `/` for a virtual filesystem, and `process.cwd()` for the host adapter.\n * An explicit absolute cwd replaces it; a relative cwd is resolved inside it. The\n * result is therefore always the one concrete absolute path `Current` requires.\n *\n * A non-absolute default throws rather than failing typed. It is the one\n * defect-level guard in this module, and deliberately so:\n * Adapters reading a value from a provider call this inside their own error channel,\n * where the throw becomes their typed failure (see `EnvDaytona.mountCwd`).\n */\nexport const resolveMountCwd = (defaultCwd: string, cwd?: string): string => {\n\tif (!posix.isAbsolute(defaultCwd)) {\n\t\tthrow new TypeError(`Sandbox default cwd must be absolute: ${defaultCwd}`);\n\t}\n\t// `resolve`, not `normalize`: normalize keeps a trailing slash, and `cwd` is\n\t// persisted — `space.location` and its id hash would read\n\t// `/workspace/` and `/workspace` as two directories and keep a row for each.\n\t//\n\t// A provider-reported default (`getWorkDir()`) or a config value is free to\n\t// carry one, so it is stripped here rather than at every reader.\n\tif (cwd === undefined) return posix.resolve(defaultCwd);\n\treturn posix.isAbsolute(cwd) ? posix.resolve(cwd) : posix.resolve(defaultCwd, cwd);\n};\n\n/**\n * Complete a mount with its {@link Mutation} queue, derived from the mount's own\n * identity and filesystem. Every layer that provides a mount goes through here,\n * so mounts of one instance always meet in the same queue.\n */\nexport const withMutation = <E, R>(\n\tlayer: EffectLayer.Layer<Current | SandboxFileSystem.Service | ShellTag, E, R>,\n): EffectLayer.Layer<Provides, E, R> =>\n\tEffectLayer.provideMerge(\n\t\tEffectLayer.effect(\n\t\t\tMutation,\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst current = yield* Current;\n\t\t\t\treturn SandboxMutation.make(current.id, current.cwd, yield* SandboxFileSystem.Service);\n\t\t\t}),\n\t\t),\n\t\tlayer,\n\t);\n\n/**\n * Bind a cwd-neutral transport to one mount.\n *\n * The transport underneath is shared between\n * mounts and stays rooted at the namespace root, and everything directory-shaped\n * happens here, once per mount. Two mounts of one namespace at different working\n * directories therefore coexist without seeing or moving each other's.\n *\n * It consumes the same two tags it provides — the transport is supplied by the\n * layer this is composed over, not by itself.\n */\nexport const mount = (identity: Identity): EffectLayer.Layer<Provides, never, SandboxFileSystem.Service | ShellTag> =>\n\tEffectLayer.mergeAll(\n\t\tEffectLayer.succeed(Current, identity),\n\t\tEffectLayer.effect(\n\t\t\tSandboxFileSystem.Service,\n\t\t\tEffect.map(SandboxFileSystem.Service, (fs) => SandboxFileSystem.withCwd(fs, identity.cwd)),\n\t\t),\n\t\tEffectLayer.effect(\n\t\t\tShellTag,\n\t\t\tEffect.map(ShellTag, (shell: ISandboxExe) => shellWithCwd(shell, identity.cwd)),\n\t\t),\n\t).pipe(withMutation);\n\n/**\n * Just the identity tag, with no filesystem or shell beneath it. For consumers\n * assembled from stubs — a test that runs `Project` over a fake filesystem still\n * needs to know which namespace it is in.\n */\nexport const identityLayer = (identity: Identity) => EffectLayer.succeed(Current, identity);\n\n/** The host identity alone. See {@link identityLayer}. */\nexport const hostLayer = (cwd: string) => identityLayer(host(cwd));\n\n/**\n * The host, rooted at `cwd`. Always `SandboxInstance.ID.local`: the working\n * directory selects where relative paths resolve, it does not make a second host\n * namespace — two mounts rooted at different directories still agree on absolute\n * paths.\n *\n * The host coordinate is explicit so a caller cannot accidentally substitute ambient process\n * state for the application or session directory it owns.\n */\nexport const host = (cwd: string): Identity => ({\n\tid: SandboxInstance.ID.local,\n\tdriver: \"local\" as SandboxDriver.Name,\n\tkind: \"local\",\n\tcwd: resolveMountCwd(cwd),\n});\n\n/**\n * A VFS-backed namespace. The id is minted per call unless one is named, because\n * building one of these builds a fresh VFS: N unnamed calls are N distinct\n * namespaces, none of which outlives the process. A file-backed store is the\n * exception — its file is the state, so whoever knows the file supplies the id\n * it was registered under.\n */\nexport const virtual = (input: {\n\treadonly driver: string;\n\treadonly id?: SandboxInstance.ID;\n\treadonly defaultCwd?: string;\n\treadonly cwd?: string;\n}): Identity => ({\n\tid: input.id ?? SandboxInstance.ID.create(),\n\tdriver: input.driver as SandboxDriver.Name,\n\tkind: \"virtual\",\n\tcwd: resolveMountCwd(input.defaultCwd ?? \"/\", input.cwd),\n});\n\n/**\n * A provider-hosted namespace. The id is always supplied: a remote resource's\n * durable identity is minted and recorded by whoever provisioned it, never\n * derived here from the provider's own locator.\n */\nexport const remote = (input: {\n\treadonly driver: string;\n\treadonly id: SandboxInstance.ID;\n\t/** Namespace-intrinsic default supplied or discovered by the driver. */\n\treadonly defaultCwd: string;\n\treadonly cwd?: string;\n}): Identity => ({\n\tid: input.id,\n\tdriver: input.driver as SandboxDriver.Name,\n\tkind: \"remote\",\n\tcwd: resolveMountCwd(input.defaultCwd, input.cwd),\n});\n\nexport * as SandboxIO from \"./io.ts\";\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { c as filesystem_d_exports, s as Service } from "./filesystem-Cp-KapCE.mjs";
1
+ import { c as filesystem_d_exports, n as FileSystemError, r as Interface$1, s as Service$1 } from "./filesystem-Cv2gjOJa.mjs";
2
2
  import { i as Shell$1 } from "./shell-CZ6Y4lNU.mjs";
3
3
  import { Context, Effect, Layer, Option, Schema } from "effect";
4
4
  declare namespace instance_d_exports {
@@ -370,8 +370,33 @@ declare const defineModule: <Options>(value: ModuleDefinition<Options>) => Modul
370
370
  declare const driver: <CreateConfig, RuntimeConfig extends RuntimeConfigBase>(value: Driver<CreateConfig, RuntimeConfig>) => Driver<CreateConfig, RuntimeConfig> & Registration;
371
371
  /** Attach trusted origin metadata without changing the driver implementation. */
372
372
  declare const withSource: (registration: Registration, source: Source) => Registration;
373
+ declare namespace mutation_d_exports {
374
+ export { Interface, mutation_d_exports as SandboxMutation, Service, make };
375
+ }
376
+ /**
377
+ * Serializes mutations of one file.
378
+ *
379
+ * Tool calls may run in parallel, and a file-mutating tool does read → modify →
380
+ * write. Two of those on one file interleave and the first write is lost, so a
381
+ * tool holds the file for its whole read-modify-write.
382
+ *
383
+ * A file is its sandbox instance plus its canonical path: two mounts of one
384
+ * instance share files, and a symlinked spelling of a path is the same file.
385
+ * Other files never wait. This orders the harness's own tools within this
386
+ * process only; it is not a lock against `bash` or other processes.
387
+ */
388
+ interface Interface {
389
+ /**
390
+ * Run `effect` as the only mutation of `path` in flight. Calls queue in the
391
+ * order their paths resolve, which for one spelling is the order they were made.
392
+ */
393
+ readonly withFile: <A, E, R>(path: string, effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | FileSystemError, R>;
394
+ }
395
+ declare const Service_base: Context.ServiceClass<Service, "@codeworksh/plugin/sandbox/mutation/Service", Interface>;
396
+ declare class Service extends Service_base {}
397
+ declare const make: (instance: ID, cwd: string, fs: Interface$1) => Interface;
373
398
  declare namespace io_d_exports {
374
- export { Current, FileSystem, Identity, Layer$1 as Layer, Provides, io_d_exports as SandboxIO, Shell, host, hostLayer, identityLayer, mount, remote, resolveMountCwd, virtual };
399
+ export { Current, FileSystem, Identity, Layer$1 as Layer, Mutation, Provides, io_d_exports as SandboxIO, Shell, host, hostLayer, identityLayer, mount, remote, resolveMountCwd, virtual, withMutation };
375
400
  }
376
401
  /**
377
402
  * `SandboxIO` is a **mount**: a filesystem, a shell, and the identity and
@@ -394,11 +419,14 @@ declare namespace io_d_exports {
394
419
  * the module that happens to define it. Code *inside* `sandbox/` keeps importing
395
420
  * the tag directly, since `io.ts` is built on top of it.
396
421
  */
397
- declare const FileSystem: typeof Service;
398
- type FileSystem = Service;
422
+ declare const FileSystem: typeof Service$1;
423
+ type FileSystem = Service$1;
399
424
  /** The shell tag. Re-exported here so consumers import one namespace. */
400
425
  declare const Shell: typeof Shell$1;
401
426
  type Shell = Shell$1;
427
+ /** Per-file mutation ordering for this mount's instance. Re-exported here so consumers import one namespace. */
428
+ declare const Mutation: typeof Service;
429
+ type Mutation = Service;
402
430
  /**
403
431
  * What a mount sees: immutable identity, plus the working directory resolved for
404
432
  * *this* mount.
@@ -420,7 +448,7 @@ declare const Current_base: Context.ServiceClass<Current, "@codeworksh/plugin/sa
420
448
  /** Identity and working directory of the current mount. */
421
449
  declare class Current extends Current_base {}
422
450
  /** Everything a mount provides. */
423
- type Provides = Current | Service | Shell$1;
451
+ type Provides = Current | Service$1 | Shell$1 | Service;
424
452
  /** A built mount. */
425
453
  type Layer$1<E = never, RIn = never> = Layer.Layer<Provides, E, RIn>;
426
454
  /**
@@ -437,6 +465,12 @@ type Layer$1<E = never, RIn = never> = Layer.Layer<Provides, E, RIn>;
437
465
  * where the throw becomes their typed failure (see `EnvDaytona.mountCwd`).
438
466
  */
439
467
  declare const resolveMountCwd: (defaultCwd: string, cwd?: string) => string;
468
+ /**
469
+ * Complete a mount with its {@link Mutation} queue, derived from the mount's own
470
+ * identity and filesystem. Every layer that provides a mount goes through here,
471
+ * so mounts of one instance always meet in the same queue.
472
+ */
473
+ declare const withMutation: <E, R>(layer: Layer.Layer<Current | Service$1 | Shell$1, E, R>) => Layer.Layer<Provides, E, R>;
440
474
  /**
441
475
  * Bind a cwd-neutral transport to one mount.
442
476
  *
@@ -448,7 +482,7 @@ declare const resolveMountCwd: (defaultCwd: string, cwd?: string) => string;
448
482
  * It consumes the same two tags it provides — the transport is supplied by the
449
483
  * layer this is composed over, not by itself.
450
484
  */
451
- declare const mount: (identity: Identity) => Layer.Layer<Provides, never, Service | Shell$1>;
485
+ declare const mount: (identity: Identity) => Layer.Layer<Provides, never, Service$1 | Shell$1>;
452
486
  /**
453
487
  * Just the identity tag, with no filesystem or shell beneath it. For consumers
454
488
  * assembled from stubs — a test that runs `Project` over a fake filesystem still
@@ -493,5 +527,5 @@ declare const remote: (input: {
493
527
  readonly cwd?: string;
494
528
  }) => Identity;
495
529
  //#endregion
496
- export { SandboxTransitionConflictError as $, apiVersion as A, SandboxDriverLoadError as B, Observed as C, RuntimeConfigBase as D, Registration as E, withSource as F, SandboxMustBeStoppedError as G, SandboxDriverNotRegisteredError as H, Redactor as I, SandboxReadError as J, SandboxNotFoundError as K, SandboxBusyError as L, driver as M, driver_d_exports as N, RuntimeInput as O, erase as P, SandboxStopError as Q, SandboxCreateError as R, Name as S, toField as St, Registered as T, SandboxDriverRegistrationError as U, SandboxDriverLoadPhase as V, SandboxMountError as W, SandboxRegisterError as X, SandboxRefreshError as Y, SandboxRemovedError as Z, Capabilities as _, fromField as _t, Provides as a, providerError as at, Module as b, mountable as bt, hostLayer as c, sanitizeError as ct, mount as d, Kind as dt, SandboxUnavailError as et, remote as f, Ownership as ft, ApiVersion as g, fromColumn as gt, AbsolutePath as h, Usage as ht, Layer$1 as i, makeRedactor as it, defineModule as j, Source as k, identityLayer as l, ID as lt, virtual as m, Status as mt, FileSystem as n, SandboxWakeError as nt, Shell as o, providerErrorCause as ot, resolveMountCwd as p, PersistedError as pt, SandboxProviderError as q, Identity as r, errors_d_exports as rt, host as s, providerErrorIsNotFound as st, Current as t, SandboxUnsupportedError as tt, io_d_exports as u, Info as ut, Definition as v, instance_d_exports as vt, Provisioned as w, ModuleDefinition as x, toColumn as xt, Driver as y, isMountable as yt, SandboxDestroyError as z };
497
- //# sourceMappingURL=io-BYs7hbiY.d.mts.map
530
+ export { SandboxRemovedError as $, RuntimeInput as A, SandboxCreateError as B, ModuleDefinition as C, toColumn as Ct, Registered as D, Provisioned as E, driver_d_exports as F, SandboxDriverRegistrationError as G, SandboxDriverLoadError as H, erase as I, SandboxNotFoundError as J, SandboxMountError as K, withSource as L, apiVersion as M, defineModule as N, Registration as O, driver as P, SandboxRegisterError as Q, Redactor as R, Module as S, mountable as St, Observed as T, SandboxDriverLoadPhase as U, SandboxDestroyError as V, SandboxDriverNotRegisteredError as W, SandboxReadError as X, SandboxProviderError as Y, SandboxRefreshError as Z, AbsolutePath as _, Usage as _t, Mutation as a, errors_d_exports as at, Definition as b, instance_d_exports as bt, host as c, providerErrorCause as ct, io_d_exports as d, ID as dt, SandboxStopError as et, mount as f, Info as ft, withMutation as g, Status as gt, virtual as h, PersistedError as ht, Layer$1 as i, SandboxWakeError as it, Source as j, RuntimeConfigBase as k, hostLayer as l, providerErrorIsNotFound as lt, resolveMountCwd as m, Ownership as mt, FileSystem as n, SandboxUnavailError as nt, Provides as o, makeRedactor as ot, remote as p, Kind as pt, SandboxMustBeStoppedError as q, Identity as r, SandboxUnsupportedError as rt, Shell as s, providerError as st, Current as t, SandboxTransitionConflictError as tt, identityLayer as u, sanitizeError as ut, ApiVersion as v, fromColumn as vt, Name as w, toField as wt, Driver as x, isMountable as xt, Capabilities as y, fromField as yt, SandboxBusyError as z };
531
+ //# sourceMappingURL=io-DhT4Y0Lw.d.mts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeworksh/plugin",
3
- "version": "0.1.0-canary.17.1.g648af395",
3
+ "version": "0.1.0-canary.18.1.g00a873ad",
4
4
  "description": "SDK for building CodeWork plugins — the plugin, tool, and sandbox contracts shared with @codeworksh/harness.",
5
5
  "keywords": [
6
6
  "agent",
@@ -168,7 +168,7 @@
168
168
  "uuidv7": "^1.2.1"
169
169
  },
170
170
  "peerDependencies": {
171
- "@codeworksh/aikit": "0.10.0-canary.17.1.g648af395",
171
+ "@codeworksh/aikit": "0.10.0-canary.18.1.g00a873ad",
172
172
  "effect": "4.0.1"
173
173
  }
174
174
  }
@@ -1,7 +1,7 @@
1
- import { i as Definition, o as Payload, r as Data, s as PublishOptions } from "./event-mKxToqmh.mjs";
1
+ import { i as Definition, o as Payload, r as Data, s as PublishOptions } from "./event-6sTQ_4bq.mjs";
2
2
  import { n as SessionID } from "./ids-CHjmAdTc.mjs";
3
3
  import { o as Service, r as Info } from "./location-Q39els63.mjs";
4
- import { a as Provides, r as Identity, u as io_d_exports } from "./io-BYs7hbiY.mjs";
4
+ import { d as io_d_exports, o as Provides, r as Identity } from "./io-DhT4Y0Lw.mjs";
5
5
  import { i as Info$1 } from "./settings-B6-grSTA.mjs";
6
6
  import { t as section_d_exports } from "./plugin/section.mjs";
7
7
  import { n as prompt_d_exports, t as PromptRegistry } from "./prompt-DWaA5ZXj.mjs";
@@ -138,4 +138,4 @@ declare namespace plugin_d_exports {
138
138
  }
139
139
  //#endregion
140
140
  export { define as a, PluginOptions as c, PluginSpec as d, Config as f, PluginRegistry as g, SharedPluginContext as h, PluginKind as i, PluginPatch as l, PromptResolver as m, Mount as n, domains as o, Events as p, Plugin as r, rank as s, plugin_d_exports as t, PluginRef as u };
141
- //# sourceMappingURL=plugin-DBrMUV15.d.mts.map
141
+ //# sourceMappingURL=plugin-Bc2vSo2k.d.mts.map
package/plugin.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as section_d_exports } from "./plugin/section.mjs";
2
2
  import { n as prompt_d_exports } from "./prompt-DWaA5ZXj.mjs";
3
3
  import { p as tool_d_exports } from "./tool-BoVqkYvL.mjs";
4
- import { a as define, c as PluginOptions, d as PluginSpec, f as Config, g as PluginRegistry, h as SharedPluginContext, i as PluginKind, l as PluginPatch, m as PromptResolver, n as Mount, o as domains, p as Events, r as Plugin, s as rank, u as PluginRef } from "./plugin-DBrMUV15.mjs";
4
+ import { a as define, c as PluginOptions, d as PluginSpec, f as Config, g as PluginRegistry, h as SharedPluginContext, i as PluginKind, l as PluginPatch, m as PromptResolver, n as Mount, o as domains, p as Events, r as Plugin, s as rank, u as PluginRef } from "./plugin-Bc2vSo2k.mjs";
5
5
  export { type Config, type Events, type Mount, type Plugin, type PluginKind, type PluginOptions, type PluginPatch, type PluginRef, type PluginRegistry, type PluginSpec, prompt_d_exports as Prompt, type PromptResolver, section_d_exports as Section, type SharedPluginContext, tool_d_exports as Tool, define, domains, rank };
@@ -1,2 +1,2 @@
1
- import { A as apiVersion, C as Observed, D as RuntimeConfigBase, E as Registration, F as withSource, M as driver, N as driver_d_exports, O as RuntimeInput, P as erase, S as Name, T as Registered, _ as Capabilities, b as Module, g as ApiVersion, h as AbsolutePath, j as defineModule, k as Source, v as Definition, w as Provisioned, x as ModuleDefinition, y as Driver } from "../io-BYs7hbiY.mjs";
1
+ import { A as RuntimeInput, C as ModuleDefinition, D as Registered, E as Provisioned, F as driver_d_exports, I as erase, L as withSource, M as apiVersion, N as defineModule, O as Registration, P as driver, S as Module, T as Observed, _ as AbsolutePath, b as Definition, j as Source, k as RuntimeConfigBase, v as ApiVersion, w as Name, x as Driver, y as Capabilities } from "../io-DhT4Y0Lw.mjs";
2
2
  export { AbsolutePath, ApiVersion, Capabilities, Definition, Driver, Module, ModuleDefinition, Name, Observed, Provisioned, Registered, Registration, RuntimeConfigBase, RuntimeInput, driver_d_exports as SandboxDriver, Source, apiVersion, driver, erase, defineModule as module, withSource };
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.mjs";
2
2
  import "./instance.mjs";
3
- import "./io.mjs";
3
+ import "../io-5PrgzDTe.mjs";
4
4
  import { Schema } from "effect";
5
5
  //#region src/sandbox/driver.ts
6
6
  var driver_exports = /* @__PURE__ */ __exportAll({
@@ -1,2 +1,2 @@
1
- import { $ as SandboxTransitionConflictError, B as SandboxDriverLoadError, G as SandboxMustBeStoppedError, H as SandboxDriverNotRegisteredError, I as Redactor, J as SandboxReadError, K as SandboxNotFoundError, L as SandboxBusyError, Q as SandboxStopError, R as SandboxCreateError, U as SandboxDriverRegistrationError, V as SandboxDriverLoadPhase, W as SandboxMountError, X as SandboxRegisterError, Y as SandboxRefreshError, Z as SandboxRemovedError, at as providerError, ct as sanitizeError, et as SandboxUnavailError, it as makeRedactor, nt as SandboxWakeError, ot as providerErrorCause, q as SandboxProviderError, rt as errors_d_exports, st as providerErrorIsNotFound, tt as SandboxUnsupportedError, z as SandboxDestroyError } from "../io-BYs7hbiY.mjs";
1
+ import { $ as SandboxRemovedError, B as SandboxCreateError, G as SandboxDriverRegistrationError, H as SandboxDriverLoadError, J as SandboxNotFoundError, K as SandboxMountError, Q as SandboxRegisterError, R as Redactor, U as SandboxDriverLoadPhase, V as SandboxDestroyError, W as SandboxDriverNotRegisteredError, X as SandboxReadError, Y as SandboxProviderError, Z as SandboxRefreshError, at as errors_d_exports, ct as providerErrorCause, et as SandboxStopError, it as SandboxWakeError, lt as providerErrorIsNotFound, nt as SandboxUnavailError, ot as makeRedactor, q as SandboxMustBeStoppedError, rt as SandboxUnsupportedError, st as providerError, tt as SandboxTransitionConflictError, ut as sanitizeError, z as SandboxBusyError } from "../io-DhT4Y0Lw.mjs";
2
2
  export { Redactor, SandboxBusyError, SandboxCreateError, SandboxDestroyError, SandboxDriverLoadError, SandboxDriverLoadPhase, SandboxDriverNotRegisteredError, SandboxDriverRegistrationError, errors_d_exports as SandboxError, SandboxMountError, SandboxMustBeStoppedError, SandboxNotFoundError, SandboxProviderError, SandboxReadError, SandboxRefreshError, SandboxRegisterError, SandboxRemovedError, SandboxStopError, SandboxTransitionConflictError, SandboxUnavailError, SandboxUnsupportedError, SandboxWakeError, makeRedactor, providerError, providerErrorCause, providerErrorIsNotFound, sanitizeError };
@@ -1,2 +1,2 @@
1
- import { a as Provider, c as filesystem_d_exports, d as realpathScripts, f as validateRmOptions, i as OperationUnsupportedError, l as fromProvider, n as FileSystemError, o as RmOptions, p as withCwd, r as Interface, s as Service, t as FileStat, u as isNotFoundError } from "../filesystem-Cp-KapCE.mjs";
1
+ import { a as Provider, c as filesystem_d_exports, d as realpathScripts, f as validateRmOptions, i as OperationUnsupportedError, l as fromProvider, n as FileSystemError, o as RmOptions, p as withCwd, r as Interface, s as Service, t as FileStat, u as isNotFoundError } from "../filesystem-Cv2gjOJa.mjs";
2
2
  export { FileStat, FileSystemError, Interface, OperationUnsupportedError, Provider, RmOptions, filesystem_d_exports as SandboxFileSystem, Service, fromProvider, isNotFoundError, realpathScripts, validateRmOptions, withCwd };
@@ -58,12 +58,18 @@ const isNotFoundError = (cause) => {
58
58
  return code === "ENOENT" || code === "ENOTDIR";
59
59
  };
60
60
  /**
61
- * Shell forms of `realpath` for backends that only expose a process API.
62
- * `pwd -P` is the portable primitive: directories resolve directly, anything
63
- * else resolves its parent and keeps the final name as given. Run as
64
- * `sh -c <script> _ <path>`; try the first, fall back to the second.
61
+ * Shell forms of `realpath` for backends that only expose a process API. Run as
62
+ * `sh -c <script> _ <path>`, trying each in turn. `realpath -e` (coreutils)
63
+ * resolves every component, a symlinked file included, and fails on a missing
64
+ * path. Where it is absent, `pwd -P` is the portable primitive: directories
65
+ * resolve directly, anything else resolves its parent and keeps the final name
66
+ * as given — so a symlinked *file* stays unresolved there.
65
67
  */
66
- const realpathScripts = ["cd -- \"$1\" && pwd -P", "cd -- \"$(dirname -- \"$1\")\" && printf '%s/%s' \"$(pwd -P)\" \"$(basename -- \"$1\")\""];
68
+ const realpathScripts = [
69
+ "realpath -e -- \"$1\"",
70
+ "cd -- \"$1\" && pwd -P",
71
+ "cd -- \"$(dirname -- \"$1\")\" && printf '%s/%s' \"$(pwd -P)\" \"$(basename -- \"$1\")\""
72
+ ];
67
73
  /** The runtime filesystem service — the live {@link Interface} for the active sandbox. */
68
74
  var Service = class extends Context.Service()("@codeworksh/plugin/sandbox/filesystem/Service") {};
69
75
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"filesystem.mjs","names":[],"sources":["../../../src/sandbox/filesystem.ts"],"sourcesContent":["import { Context, Effect, Schema } from \"effect\";\nimport { posix } from \"../posix.ts\";\n\n/**\n * The runtime filesystem contract, independent of any backend.\n *\n * Two surfaces, deliberately:\n * - {@link Provider} is what a backend implements — plain promises that reject,\n * matching every SDK we wrap.\n * - {@link Interface} is what the harness consumes — Effect with a typed error\n * channel and tracing spans. {@link fromProvider} bridges the two exactly\n * once, so no consumer ever writes `Effect.tryPromise` against a filesystem.\n *\n * Implementations:\n * - Local:\n * implement it over a VFS (`./local`);\n * local filesystem use OS primitives; hence have broader filesytem capabilities.\n *\n * - Remote:\n * implement it over a provider (`./remote`).\n * remote filesytems depends on the interface provided by the remote provider; hence can have limited filesytem capabilities.\n *\n * `isFile`/`isDirectory` are required booleans; size, mtime, and isSymbolicLink are omitted when the\n * backend cannot report them — never fabricated.\n *\n * **Paths are POSIX, and the harness is Unix-only (for now!).** Every path uses `/`\n * separators on both the host and inside a sandbox — Windows is not supported,\n * so no translation layer exists. Consumers must use the shared Effect POSIX\n * path implementation, never the platform default, or a host running the harness would\n * impose its own flavour on a remote sandbox's paths. Relative paths resolve\n * against the backend's configured `cwd`.\n */\n\nexport class OperationUnsupportedError extends Schema.TaggedError<OperationUnsupportedError>()(\n\t\"OperationUnsupportedError\",\n\t{\n\t\toperation: Schema.String,\n\t\tmessage: Schema.String,\n\t},\n) {}\n\n/** A backend operation failed. `cause` carries the provider's own rejection. */\nexport class FileSystemError extends Schema.TaggedError<FileSystemError>()(\"SandboxFileSystemError\", {\n\tmethod: Schema.String,\n\tpath: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {}\n\nexport interface FileStat {\n\treadonly isFile: boolean;\n\treadonly isDirectory: boolean;\n\treadonly isSymbolicLink?: boolean;\n\treadonly size?: number;\n\treadonly mtime?: Date;\n}\n\nexport interface RmOptions {\n\treadonly recursive?: boolean;\n\treadonly force?: boolean;\n}\n\n/** Whether a provider failure means the path itself is definitively absent. */\nexport const isNotFoundError = (cause: unknown) => {\n\tconst code = (cause as NodeJS.ErrnoException | undefined)?.code;\n\treturn code === \"ENOENT\" || code === \"ENOTDIR\";\n};\n\n/**\n * Shell forms of `realpath` for backends that only expose a process API.\n * `pwd -P` is the portable primitive: directories resolve directly, anything\n * else resolves its parent and keeps the final name as given. Run as\n * `sh -c <script> _ <path>`; try the first, fall back to the second.\n */\nexport const realpathScripts = [\n\t'cd -- \"$1\" && pwd -P',\n\t'cd -- \"$(dirname -- \"$1\")\" && printf \\'%s/%s\\' \"$(pwd -P)\" \"$(basename -- \"$1\")\"',\n] as const;\n\n/**\n * The backend-facing contract. Backends author plain promises and let them\n * reject; {@link fromProvider} turns rejections into typed failures.\n */\nexport interface Provider {\n\treadonly readFile: (path: string) => Promise<string>;\n\treadonly readFileBuffer: (path: string) => Promise<Uint8Array>;\n\t/**\n\t * Write the file. Parents may be missing — do not create them here;\n\t * {@link fromProvider} owns that guarantee for every backend.\n\t */\n\treadonly writeFile: (path: string, content: string | Uint8Array) => Promise<void>;\n\treadonly stat: (path: string) => Promise<FileStat>;\n\treadonly readdir: (path: string) => Promise<string[]>;\n\treadonly exists: (path: string) => Promise<boolean>;\n\treadonly mkdir: (path: string, options?: { recursive?: boolean }) => Promise<void>;\n\treadonly rm: (path: string, options?: RmOptions) => Promise<void>;\n\t/** Canonical absolute path with symlinks resolved; rejects when the path does not exist. */\n\treadonly realpath: (path: string) => Promise<string>;\n\t/**\n\t * Metadata for the directory entry itself rather than a symlink's target.\n\t * Optional: a backend whose `stat` has mixed symlink semantics implements it\n\t * so symlink identity is asked for explicitly, never inferred.\n\t */\n\treadonly lstat?: (path: string) => Promise<FileStat>;\n}\n\n/**\n * The consumer-facing contract. `exists` distinguishes \"absent\" from \"could not\n * tell\": a backend failure is a typed failure, not `false`, so a caller acting\n * on absence never acts on a network blip. Use `SandboxFs.existsOrFalse` where\n * a best-effort answer really is wanted.\n */\nexport interface Interface {\n\treadonly readFile: (path: string) => Effect.Effect<string, FileSystemError>;\n\treadonly readFileBuffer: (path: string) => Effect.Effect<Uint8Array, FileSystemError>;\n\t/** Creates missing parent directories, on every backend. */\n\treadonly writeFile: (path: string, content: string | Uint8Array) => Effect.Effect<void, FileSystemError>;\n\treadonly stat: (path: string) => Effect.Effect<FileStat, FileSystemError>;\n\treadonly readdir: (path: string) => Effect.Effect<string[], FileSystemError>;\n\treadonly exists: (path: string) => Effect.Effect<boolean, FileSystemError>;\n\treadonly mkdir: (path: string, options?: { recursive?: boolean }) => Effect.Effect<void, FileSystemError>;\n\treadonly rm: (path: string, options?: RmOptions) => Effect.Effect<void, FileSystemError | OperationUnsupportedError>;\n\t/** Canonical absolute path with symlinks resolved; fails when the path does not exist. */\n\treadonly realpath: (path: string) => Effect.Effect<string, FileSystemError>;\n\t// `lstat` is present only when the backend supports it; check before calling.\n\treadonly lstat?: (path: string) => Effect.Effect<FileStat, FileSystemError>;\n}\n\n/** The runtime filesystem service — the live {@link Interface} for the active sandbox. */\nexport class Service extends Context.Service<Service, Interface>()(\"@codeworksh/plugin/sandbox/filesystem/Service\") {}\n\n/**\n * Reject `rm` options a provider does not implement, before any mutation. Only\n * `recursive` and `force` are part of the contract; anything else is refused\n * loudly rather than silently ignored.\n */\nexport const validateRmOptions = (\n\toptions: RmOptions | undefined,\n\toperation = \"rm\",\n): Effect.Effect<void, OperationUnsupportedError> =>\n\tEffect.suspend(() => {\n\t\tfor (const option of Object.keys((options ?? {}) as Record<string, unknown>)) {\n\t\t\tif (option === \"recursive\" || option === \"force\") continue;\n\t\t\treturn Effect.fail(new OperationUnsupportedError({ operation, message: `Unsupported rm option: ${option}` }));\n\t\t}\n\t\treturn Effect.void;\n\t});\n\n/**\n * Lift a {@link Provider} into the runtime {@link Interface}: one place that\n * converts rejections into {@link FileSystemError}, validates `rm` options,\n * creates missing parents on write, and names a tracing span per operation.\n */\nexport const fromProvider = (provider: Provider): Interface => {\n\tconst attempt = <A>(method: string, path: string, run: () => Promise<A>) =>\n\t\tEffect.tryPromise({ try: run, catch: (cause) => new FileSystemError({ method, path, cause }) });\n\n\t// The parent-creation guarantee, installed once for every backend instead of\n\t// re-implemented per provider: anything that reaches `Interface` reaches it\n\t// through here, so a backend cannot forget it.\n\t//\n\t// Lazy by design — try the write first, so the happy path stays a single call\n\t// and no remote backend pays a round-trip per write. A failure is usually a\n\t// missing parent, so create it and retry once. The mkdir's own error is\n\t// dropped on purpose: when the write failed for some other reason (EACCES,\n\t// EROFS, a dropped connection), the retry reproduces it, and *that* is the\n\t// failure the caller must see rather than a misleading mkdir error standing\n\t// in for it.\n\tconst writeCreatingParents = (path: string, content: string | Uint8Array) => {\n\t\tconst write = attempt(\"writeFile\", path, () => provider.writeFile(path, content));\n\t\tconst parent = posix.dirname(path);\n\t\treturn write.pipe(\n\t\t\tEffect.catch(() =>\n\t\t\t\tattempt(\"mkdir\", parent, () => provider.mkdir(parent, { recursive: true })).pipe(\n\t\t\t\t\tEffect.ignore,\n\t\t\t\t\tEffect.andThen(write),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t};\n\n\treturn {\n\t\treadFile: Effect.fn(\"SandboxFileSystem.readFile\")((path: string) =>\n\t\t\tattempt(\"readFile\", path, () => provider.readFile(path)),\n\t\t),\n\t\treadFileBuffer: Effect.fn(\"SandboxFileSystem.readFileBuffer\")((path: string) =>\n\t\t\tattempt(\"readFileBuffer\", path, () => provider.readFileBuffer(path)),\n\t\t),\n\t\twriteFile: Effect.fn(\"SandboxFileSystem.writeFile\")(writeCreatingParents),\n\t\tstat: Effect.fn(\"SandboxFileSystem.stat\")((path: string) => attempt(\"stat\", path, () => provider.stat(path))),\n\t\t// carried through only when the backend actually implements it\n\t\t...(provider.lstat === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tlstat: Effect.fn(\"SandboxFileSystem.lstat\")((path: string) =>\n\t\t\t\t\t\tattempt(\"lstat\", path, () => provider.lstat!(path)),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\treaddir: Effect.fn(\"SandboxFileSystem.readdir\")((path: string) =>\n\t\t\tattempt(\"readdir\", path, () => provider.readdir(path)),\n\t\t),\n\t\t// A backend that cannot answer fails; it does not report \"absent\". A\n\t\t// caller acting on absence — deleting a record, say — must not be told\n\t\t// the path is gone because a token expired or a request timed out.\n\t\texists: Effect.fn(\"SandboxFileSystem.exists\")((path: string) =>\n\t\t\tattempt(\"exists\", path, () => provider.exists(path)),\n\t\t),\n\t\tmkdir: Effect.fn(\"SandboxFileSystem.mkdir\")((path: string, options?: { recursive?: boolean }) =>\n\t\t\tattempt(\"mkdir\", path, () => provider.mkdir(path, options)),\n\t\t),\n\t\trm: Effect.fn(\"SandboxFileSystem.rm\")((path: string, options?: RmOptions) =>\n\t\t\tvalidateRmOptions(options).pipe(Effect.andThen(attempt(\"rm\", path, () => provider.rm(path, options)))),\n\t\t),\n\t\trealpath: Effect.fn(\"SandboxFileSystem.realpath\")((path: string) =>\n\t\t\tattempt(\"realpath\", path, () => provider.realpath(path)),\n\t\t),\n\t};\n};\n\n/**\n * Bind a cwd-neutral filesystem to one mount's working directory.\n *\n * The counterpart of `Shell.withCwd`, and the reason relative paths mean the\n * same thing to both: a shared transport stays rooted at the namespace root, so\n * resolution happens here, per mount, rather than inside a VFS whose `chdir` is\n * global state two mounts would fight over.\n */\nexport const withCwd = (fs: Interface, cwd: string): Interface => {\n\tconst at = (path: string) => posix.resolve(cwd, path);\n\treturn {\n\t\treadFile: (path) => fs.readFile(at(path)),\n\t\treadFileBuffer: (path) => fs.readFileBuffer(at(path)),\n\t\twriteFile: (path, content) => fs.writeFile(at(path), content),\n\t\tstat: (path) => fs.stat(at(path)),\n\t\treaddir: (path) => fs.readdir(at(path)),\n\t\texists: (path) => fs.exists(at(path)),\n\t\tmkdir: (path, options) => fs.mkdir(at(path), options),\n\t\trm: (path, options) => fs.rm(at(path), options),\n\t\trealpath: (path) => fs.realpath(at(path)),\n\t\t// carried through only when the backend implements it, so a caller can\n\t\t// still detect absence by checking the property\n\t\t...(fs.lstat === undefined ? {} : { lstat: (path: string) => fs.lstat!(at(path)) }),\n\t};\n};\n\nexport * as SandboxFileSystem from \"./filesystem.ts\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"filesystem.mjs","names":[],"sources":["../../../src/sandbox/filesystem.ts"],"sourcesContent":["import { Context, Effect, Schema } from \"effect\";\nimport { posix } from \"../posix.ts\";\n\n/**\n * The runtime filesystem contract, independent of any backend.\n *\n * Two surfaces, deliberately:\n * - {@link Provider} is what a backend implements — plain promises that reject,\n * matching every SDK we wrap.\n * - {@link Interface} is what the harness consumes — Effect with a typed error\n * channel and tracing spans. {@link fromProvider} bridges the two exactly\n * once, so no consumer ever writes `Effect.tryPromise` against a filesystem.\n *\n * Implementations:\n * - Local:\n * implement it over a VFS (`./local`);\n * local filesystem use OS primitives; hence have broader filesytem capabilities.\n *\n * - Remote:\n * implement it over a provider (`./remote`).\n * remote filesytems depends on the interface provided by the remote provider; hence can have limited filesytem capabilities.\n *\n * `isFile`/`isDirectory` are required booleans; size, mtime, and isSymbolicLink are omitted when the\n * backend cannot report them — never fabricated.\n *\n * **Paths are POSIX, and the harness is Unix-only (for now!).** Every path uses `/`\n * separators on both the host and inside a sandbox — Windows is not supported,\n * so no translation layer exists. Consumers must use the shared Effect POSIX\n * path implementation, never the platform default, or a host running the harness would\n * impose its own flavour on a remote sandbox's paths. Relative paths resolve\n * against the backend's configured `cwd`.\n */\n\nexport class OperationUnsupportedError extends Schema.TaggedError<OperationUnsupportedError>()(\n\t\"OperationUnsupportedError\",\n\t{\n\t\toperation: Schema.String,\n\t\tmessage: Schema.String,\n\t},\n) {}\n\n/** A backend operation failed. `cause` carries the provider's own rejection. */\nexport class FileSystemError extends Schema.TaggedError<FileSystemError>()(\"SandboxFileSystemError\", {\n\tmethod: Schema.String,\n\tpath: Schema.String,\n\tcause: Schema.optional(Schema.Defect()),\n}) {}\n\nexport interface FileStat {\n\treadonly isFile: boolean;\n\treadonly isDirectory: boolean;\n\treadonly isSymbolicLink?: boolean;\n\treadonly size?: number;\n\treadonly mtime?: Date;\n}\n\nexport interface RmOptions {\n\treadonly recursive?: boolean;\n\treadonly force?: boolean;\n}\n\n/** Whether a provider failure means the path itself is definitively absent. */\nexport const isNotFoundError = (cause: unknown) => {\n\tconst code = (cause as NodeJS.ErrnoException | undefined)?.code;\n\treturn code === \"ENOENT\" || code === \"ENOTDIR\";\n};\n\n/**\n * Shell forms of `realpath` for backends that only expose a process API. Run as\n * `sh -c <script> _ <path>`, trying each in turn. `realpath -e` (coreutils)\n * resolves every component, a symlinked file included, and fails on a missing\n * path. Where it is absent, `pwd -P` is the portable primitive: directories\n * resolve directly, anything else resolves its parent and keeps the final name\n * as given — so a symlinked *file* stays unresolved there.\n */\nexport const realpathScripts = [\n\t'realpath -e -- \"$1\"',\n\t'cd -- \"$1\" && pwd -P',\n\t'cd -- \"$(dirname -- \"$1\")\" && printf \\'%s/%s\\' \"$(pwd -P)\" \"$(basename -- \"$1\")\"',\n] as const;\n\n/**\n * The backend-facing contract. Backends author plain promises and let them\n * reject; {@link fromProvider} turns rejections into typed failures.\n */\nexport interface Provider {\n\treadonly readFile: (path: string) => Promise<string>;\n\treadonly readFileBuffer: (path: string) => Promise<Uint8Array>;\n\t/**\n\t * Write the file. Parents may be missing — do not create them here;\n\t * {@link fromProvider} owns that guarantee for every backend.\n\t */\n\treadonly writeFile: (path: string, content: string | Uint8Array) => Promise<void>;\n\treadonly stat: (path: string) => Promise<FileStat>;\n\treadonly readdir: (path: string) => Promise<string[]>;\n\treadonly exists: (path: string) => Promise<boolean>;\n\treadonly mkdir: (path: string, options?: { recursive?: boolean }) => Promise<void>;\n\treadonly rm: (path: string, options?: RmOptions) => Promise<void>;\n\t/** Canonical absolute path with symlinks resolved; rejects when the path does not exist. */\n\treadonly realpath: (path: string) => Promise<string>;\n\t/**\n\t * Metadata for the directory entry itself rather than a symlink's target.\n\t * Optional: a backend whose `stat` has mixed symlink semantics implements it\n\t * so symlink identity is asked for explicitly, never inferred.\n\t */\n\treadonly lstat?: (path: string) => Promise<FileStat>;\n}\n\n/**\n * The consumer-facing contract. `exists` distinguishes \"absent\" from \"could not\n * tell\": a backend failure is a typed failure, not `false`, so a caller acting\n * on absence never acts on a network blip. Use `SandboxFs.existsOrFalse` where\n * a best-effort answer really is wanted.\n */\nexport interface Interface {\n\treadonly readFile: (path: string) => Effect.Effect<string, FileSystemError>;\n\treadonly readFileBuffer: (path: string) => Effect.Effect<Uint8Array, FileSystemError>;\n\t/** Creates missing parent directories, on every backend. */\n\treadonly writeFile: (path: string, content: string | Uint8Array) => Effect.Effect<void, FileSystemError>;\n\treadonly stat: (path: string) => Effect.Effect<FileStat, FileSystemError>;\n\treadonly readdir: (path: string) => Effect.Effect<string[], FileSystemError>;\n\treadonly exists: (path: string) => Effect.Effect<boolean, FileSystemError>;\n\treadonly mkdir: (path: string, options?: { recursive?: boolean }) => Effect.Effect<void, FileSystemError>;\n\treadonly rm: (path: string, options?: RmOptions) => Effect.Effect<void, FileSystemError | OperationUnsupportedError>;\n\t/** Canonical absolute path with symlinks resolved; fails when the path does not exist. */\n\treadonly realpath: (path: string) => Effect.Effect<string, FileSystemError>;\n\t// `lstat` is present only when the backend supports it; check before calling.\n\treadonly lstat?: (path: string) => Effect.Effect<FileStat, FileSystemError>;\n}\n\n/** The runtime filesystem service — the live {@link Interface} for the active sandbox. */\nexport class Service extends Context.Service<Service, Interface>()(\"@codeworksh/plugin/sandbox/filesystem/Service\") {}\n\n/**\n * Reject `rm` options a provider does not implement, before any mutation. Only\n * `recursive` and `force` are part of the contract; anything else is refused\n * loudly rather than silently ignored.\n */\nexport const validateRmOptions = (\n\toptions: RmOptions | undefined,\n\toperation = \"rm\",\n): Effect.Effect<void, OperationUnsupportedError> =>\n\tEffect.suspend(() => {\n\t\tfor (const option of Object.keys((options ?? {}) as Record<string, unknown>)) {\n\t\t\tif (option === \"recursive\" || option === \"force\") continue;\n\t\t\treturn Effect.fail(new OperationUnsupportedError({ operation, message: `Unsupported rm option: ${option}` }));\n\t\t}\n\t\treturn Effect.void;\n\t});\n\n/**\n * Lift a {@link Provider} into the runtime {@link Interface}: one place that\n * converts rejections into {@link FileSystemError}, validates `rm` options,\n * creates missing parents on write, and names a tracing span per operation.\n */\nexport const fromProvider = (provider: Provider): Interface => {\n\tconst attempt = <A>(method: string, path: string, run: () => Promise<A>) =>\n\t\tEffect.tryPromise({ try: run, catch: (cause) => new FileSystemError({ method, path, cause }) });\n\n\t// The parent-creation guarantee, installed once for every backend instead of\n\t// re-implemented per provider: anything that reaches `Interface` reaches it\n\t// through here, so a backend cannot forget it.\n\t//\n\t// Lazy by design — try the write first, so the happy path stays a single call\n\t// and no remote backend pays a round-trip per write. A failure is usually a\n\t// missing parent, so create it and retry once. The mkdir's own error is\n\t// dropped on purpose: when the write failed for some other reason (EACCES,\n\t// EROFS, a dropped connection), the retry reproduces it, and *that* is the\n\t// failure the caller must see rather than a misleading mkdir error standing\n\t// in for it.\n\tconst writeCreatingParents = (path: string, content: string | Uint8Array) => {\n\t\tconst write = attempt(\"writeFile\", path, () => provider.writeFile(path, content));\n\t\tconst parent = posix.dirname(path);\n\t\treturn write.pipe(\n\t\t\tEffect.catch(() =>\n\t\t\t\tattempt(\"mkdir\", parent, () => provider.mkdir(parent, { recursive: true })).pipe(\n\t\t\t\t\tEffect.ignore,\n\t\t\t\t\tEffect.andThen(write),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t};\n\n\treturn {\n\t\treadFile: Effect.fn(\"SandboxFileSystem.readFile\")((path: string) =>\n\t\t\tattempt(\"readFile\", path, () => provider.readFile(path)),\n\t\t),\n\t\treadFileBuffer: Effect.fn(\"SandboxFileSystem.readFileBuffer\")((path: string) =>\n\t\t\tattempt(\"readFileBuffer\", path, () => provider.readFileBuffer(path)),\n\t\t),\n\t\twriteFile: Effect.fn(\"SandboxFileSystem.writeFile\")(writeCreatingParents),\n\t\tstat: Effect.fn(\"SandboxFileSystem.stat\")((path: string) => attempt(\"stat\", path, () => provider.stat(path))),\n\t\t// carried through only when the backend actually implements it\n\t\t...(provider.lstat === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tlstat: Effect.fn(\"SandboxFileSystem.lstat\")((path: string) =>\n\t\t\t\t\t\tattempt(\"lstat\", path, () => provider.lstat!(path)),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\treaddir: Effect.fn(\"SandboxFileSystem.readdir\")((path: string) =>\n\t\t\tattempt(\"readdir\", path, () => provider.readdir(path)),\n\t\t),\n\t\t// A backend that cannot answer fails; it does not report \"absent\". A\n\t\t// caller acting on absence — deleting a record, say — must not be told\n\t\t// the path is gone because a token expired or a request timed out.\n\t\texists: Effect.fn(\"SandboxFileSystem.exists\")((path: string) =>\n\t\t\tattempt(\"exists\", path, () => provider.exists(path)),\n\t\t),\n\t\tmkdir: Effect.fn(\"SandboxFileSystem.mkdir\")((path: string, options?: { recursive?: boolean }) =>\n\t\t\tattempt(\"mkdir\", path, () => provider.mkdir(path, options)),\n\t\t),\n\t\trm: Effect.fn(\"SandboxFileSystem.rm\")((path: string, options?: RmOptions) =>\n\t\t\tvalidateRmOptions(options).pipe(Effect.andThen(attempt(\"rm\", path, () => provider.rm(path, options)))),\n\t\t),\n\t\trealpath: Effect.fn(\"SandboxFileSystem.realpath\")((path: string) =>\n\t\t\tattempt(\"realpath\", path, () => provider.realpath(path)),\n\t\t),\n\t};\n};\n\n/**\n * Bind a cwd-neutral filesystem to one mount's working directory.\n *\n * The counterpart of `Shell.withCwd`, and the reason relative paths mean the\n * same thing to both: a shared transport stays rooted at the namespace root, so\n * resolution happens here, per mount, rather than inside a VFS whose `chdir` is\n * global state two mounts would fight over.\n */\nexport const withCwd = (fs: Interface, cwd: string): Interface => {\n\tconst at = (path: string) => posix.resolve(cwd, path);\n\treturn {\n\t\treadFile: (path) => fs.readFile(at(path)),\n\t\treadFileBuffer: (path) => fs.readFileBuffer(at(path)),\n\t\twriteFile: (path, content) => fs.writeFile(at(path), content),\n\t\tstat: (path) => fs.stat(at(path)),\n\t\treaddir: (path) => fs.readdir(at(path)),\n\t\texists: (path) => fs.exists(at(path)),\n\t\tmkdir: (path, options) => fs.mkdir(at(path), options),\n\t\trm: (path, options) => fs.rm(at(path), options),\n\t\trealpath: (path) => fs.realpath(at(path)),\n\t\t// carried through only when the backend implements it, so a caller can\n\t\t// still detect absence by checking the property\n\t\t...(fs.lstat === undefined ? {} : { lstat: (path: string) => fs.lstat!(at(path)) }),\n\t};\n};\n\nexport * as SandboxFileSystem from \"./filesystem.ts\";\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { St as toField, _t as fromField, bt as mountable, dt as Kind, ft as Ownership, gt as fromColumn, ht as Usage, lt as ID, mt as Status, pt as PersistedError, ut as Info, vt as instance_d_exports, xt as toColumn, yt as isMountable } from "../io-BYs7hbiY.mjs";
1
+ import { Ct as toColumn, St as mountable, _t as Usage, bt as instance_d_exports, dt as ID, ft as Info, gt as Status, ht as PersistedError, mt as Ownership, pt as Kind, vt as fromColumn, wt as toField, xt as isMountable, yt as fromField } from "../io-DhT4Y0Lw.mjs";
2
2
  export { ID, Info, Kind, Ownership, PersistedError, instance_d_exports as SandboxInstance, Status, Usage, fromColumn, fromField, isMountable, mountable, toColumn, toField };
package/sandbox/io.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as Provides, c as hostLayer, d as mount, f as remote, i as Layer, l as identityLayer, m as virtual, n as FileSystem, o as Shell, p as resolveMountCwd, r as Identity, s as host, t as Current, u as io_d_exports } from "../io-BYs7hbiY.mjs";
2
- export { Current, FileSystem, Identity, Layer, Provides, io_d_exports as SandboxIO, Shell, host, hostLayer, identityLayer, mount, remote, resolveMountCwd, virtual };
1
+ import { a as Mutation, c as host, d as io_d_exports, f as mount, g as withMutation, h as virtual, i as Layer, l as hostLayer, m as resolveMountCwd, n as FileSystem, o as Provides, p as remote, r as Identity, s as Shell, t as Current, u as identityLayer } from "../io-DhT4Y0Lw.mjs";
2
+ export { Current, FileSystem, Identity, Layer, Mutation, Provides, io_d_exports as SandboxIO, Shell, host, hostLayer, identityLayer, mount, remote, resolveMountCwd, virtual, withMutation };
package/sandbox/io.mjs CHANGED
@@ -1,127 +1,3 @@
1
- import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.mjs";
2
- import { ID } from "./instance.mjs";
3
- import { posix } from "../posix.mjs";
4
- import { Service, withCwd } from "./filesystem.mjs";
5
- import { Shell as Shell$1, withCwd as withCwd$1 } from "./shell.mjs";
6
- import { Context, Effect, Layer } from "effect";
7
- //#region src/sandbox/io.ts
8
- var io_exports = /* @__PURE__ */ __exportAll({
9
- Current: () => Current,
10
- FileSystem: () => FileSystem,
11
- SandboxIO: () => io_exports,
12
- Shell: () => Shell,
13
- host: () => host,
14
- hostLayer: () => hostLayer,
15
- identityLayer: () => identityLayer,
16
- mount: () => mount,
17
- remote: () => remote,
18
- resolveMountCwd: () => resolveMountCwd,
19
- virtual: () => virtual
20
- });
21
- /**
22
- * `SandboxIO` is a **mount**: a filesystem, a shell, and the identity and
23
- * working directory they act on.
24
- *
25
- * It is the whole vocabulary a consumer needs. Project, Git, Copy, Location, and
26
- * every tool ask for `SandboxIO.FileSystem`, `SandboxIO.Shell`, and
27
- * `SandboxIO.Current` — never for a driver, an address, or a provider SDK — so
28
- * a host directory, an in-memory VFS, and a remote microVM are interchangeable
29
- * behind one contract.
30
- *
31
- * The mount neither creates nor destroys infrastructure. `SandboxInstance` is
32
- * the durable namespace it acts on — a device, which exists whether or not
33
- * anything has it mounted — and `Sandbox.Controller` is the only path that
34
- * creates, stops, or destroys one.
35
- */
36
- /**
37
- * The filesystem tag. Re-exported here so consumers import one namespace —
38
- * Project, Git, Copy, and the runner ask for `SandboxIO.FileSystem`, never for
39
- * the module that happens to define it. Code *inside* `sandbox/` keeps importing
40
- * the tag directly, since `io.ts` is built on top of it.
41
- */
42
- const FileSystem = Service;
43
- /** The shell tag. Re-exported here so consumers import one namespace. */
44
- const Shell = Shell$1;
45
- /** Identity and working directory of the current mount. */
46
- var Current = class extends Context.Service()("@codeworksh/plugin/sandbox/io/Current") {};
47
- /**
48
- * Resolve a mount's cwd without consulting ambient process state.
49
- *
50
- * The default is supplied by the namespace adapter:
51
- * provider metadata remotely, `/` for a virtual filesystem, and `process.cwd()` for the host adapter.
52
- * An explicit absolute cwd replaces it; a relative cwd is resolved inside it. The
53
- * result is therefore always the one concrete absolute path `Current` requires.
54
- *
55
- * A non-absolute default throws rather than failing typed. It is the one
56
- * defect-level guard in this module, and deliberately so:
57
- * Adapters reading a value from a provider call this inside their own error channel,
58
- * where the throw becomes their typed failure (see `EnvDaytona.mountCwd`).
59
- */
60
- const resolveMountCwd = (defaultCwd, cwd) => {
61
- if (!posix.isAbsolute(defaultCwd)) throw new TypeError(`Sandbox default cwd must be absolute: ${defaultCwd}`);
62
- if (cwd === void 0) return posix.resolve(defaultCwd);
63
- return posix.isAbsolute(cwd) ? posix.resolve(cwd) : posix.resolve(defaultCwd, cwd);
64
- };
65
- /**
66
- * Bind a cwd-neutral transport to one mount.
67
- *
68
- * The transport underneath is shared between
69
- * mounts and stays rooted at the namespace root, and everything directory-shaped
70
- * happens here, once per mount. Two mounts of one namespace at different working
71
- * directories therefore coexist without seeing or moving each other's.
72
- *
73
- * It consumes the same two tags it provides — the transport is supplied by the
74
- * layer this is composed over, not by itself.
75
- */
76
- const mount = (identity) => Layer.mergeAll(Layer.succeed(Current, identity), Layer.effect(Service, Effect.map(Service, (fs) => withCwd(fs, identity.cwd))), Layer.effect(Shell$1, Effect.map(Shell$1, (shell) => withCwd$1(shell, identity.cwd))));
77
- /**
78
- * Just the identity tag, with no filesystem or shell beneath it. For consumers
79
- * assembled from stubs — a test that runs `Project` over a fake filesystem still
80
- * needs to know which namespace it is in.
81
- */
82
- const identityLayer = (identity) => Layer.succeed(Current, identity);
83
- /** The host identity alone. See {@link identityLayer}. */
84
- const hostLayer = (cwd) => identityLayer(host(cwd));
85
- /**
86
- * The host, rooted at `cwd`. Always `SandboxInstance.ID.local`: the working
87
- * directory selects where relative paths resolve, it does not make a second host
88
- * namespace — two mounts rooted at different directories still agree on absolute
89
- * paths.
90
- *
91
- * The host coordinate is explicit so a caller cannot accidentally substitute ambient process
92
- * state for the application or session directory it owns.
93
- */
94
- const host = (cwd) => ({
95
- id: ID.local,
96
- driver: "local",
97
- kind: "local",
98
- cwd: resolveMountCwd(cwd)
99
- });
100
- /**
101
- * A VFS-backed namespace. The id is minted per call unless one is named, because
102
- * building one of these builds a fresh VFS: N unnamed calls are N distinct
103
- * namespaces, none of which outlives the process. A file-backed store is the
104
- * exception — its file is the state, so whoever knows the file supplies the id
105
- * it was registered under.
106
- */
107
- const virtual = (input) => ({
108
- id: input.id ?? ID.create(),
109
- driver: input.driver,
110
- kind: "virtual",
111
- cwd: resolveMountCwd(input.defaultCwd ?? "/", input.cwd)
112
- });
113
- /**
114
- * A provider-hosted namespace. The id is always supplied: a remote resource's
115
- * durable identity is minted and recorded by whoever provisioned it, never
116
- * derived here from the provider's own locator.
117
- */
118
- const remote = (input) => ({
119
- id: input.id,
120
- driver: input.driver,
121
- kind: "remote",
122
- cwd: resolveMountCwd(input.defaultCwd, input.cwd)
123
- });
124
- //#endregion
125
- export { Current, FileSystem, io_exports as SandboxIO, Shell, host, hostLayer, identityLayer, mount, remote, resolveMountCwd, virtual };
126
-
127
- //# sourceMappingURL=io.mjs.map
1
+ import "./instance.mjs";
2
+ import { a as host, c as io_exports, d as resolveMountCwd, f as virtual, i as Shell, l as mount, n as FileSystem, o as hostLayer, p as withMutation, r as Mutation, s as identityLayer, t as Current, u as remote } from "../io-5PrgzDTe.mjs";
3
+ export { Current, FileSystem, Mutation, io_exports as SandboxIO, Shell, host, hostLayer, identityLayer, mount, remote, resolveMountCwd, virtual, withMutation };
package/sandbox.d.mts CHANGED
@@ -1,12 +1,12 @@
1
- import { A as apiVersion, C as Observed, D as RuntimeConfigBase, E as Registration, I as Redactor, M as driver, O as RuntimeInput, S as Name, _ as Capabilities, a as Provides, at as providerError, b as Module, ct as sanitizeError, g as ApiVersion, h as AbsolutePath, i as Layer, it as makeRedactor, j as defineModule, n as FileSystem, o as Shell, ot as providerErrorCause, q as SandboxProviderError, r as Identity, st as providerErrorIsNotFound, t as Current, v as Definition, vt as instance_d_exports, w as Provisioned, x as ModuleDefinition, y as Driver } from "./io-BYs7hbiY.mjs";
2
- import { c as filesystem_d_exports } from "./filesystem-Cp-KapCE.mjs";
1
+ import { A as RuntimeInput, C as ModuleDefinition, E as Provisioned, M as apiVersion, N as defineModule, O as Registration, P as driver, R as Redactor, S as Module, T as Observed, Y as SandboxProviderError, _ as AbsolutePath, a as Mutation, b as Definition, bt as instance_d_exports, ct as providerErrorCause, g as withMutation, i as Layer, k as RuntimeConfigBase, lt as providerErrorIsNotFound, n as FileSystem, o as Provides, ot as makeRedactor, r as Identity, s as Shell, st as providerError, t as Current, ut as sanitizeError, v as ApiVersion, w as Name, x as Driver, y as Capabilities } from "./io-DhT4Y0Lw.mjs";
2
+ import { c as filesystem_d_exports } from "./filesystem-Cv2gjOJa.mjs";
3
3
  import { a as ShellError, i as Shell$1, l as quote, n as ExecResult, o as ShellOptions, r as ISandboxExe, s as fromExec, t as ExecChunk, u as quoteArgv } from "./shell-CZ6Y4lNU.mjs";
4
4
  import { SandboxResource as resource_d_exports } from "./sandbox/resource.mjs";
5
5
  declare namespace driver_d_exports {
6
6
  export { AbsolutePath, ApiVersion, Capabilities, Definition, Driver, Module, ModuleDefinition, Name, Observed, Provisioned, Registration, RuntimeConfigBase as RuntimeConfig, RuntimeConfigBase, RuntimeInput, driver_d_exports as SandboxDriver, apiVersion, driver, defineModule as module };
7
7
  }
8
8
  declare namespace io_d_exports {
9
- export { Current, FileSystem, Identity, Layer, Provides, io_d_exports as SandboxIO, Shell };
9
+ export { Current, FileSystem, Identity, Layer, Mutation, Provides, io_d_exports as SandboxIO, Shell, withMutation };
10
10
  }
11
11
  declare namespace provider_d_exports {
12
12
  export { Redactor, SandboxProviderError, makeRedactor, providerError, providerErrorCause, providerErrorIsNotFound, sanitizeError };
package/sandbox.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { SandboxInstance as instance_exports } from "./sandbox/instance.mjs";
3
3
  import { SandboxFileSystem as filesystem_exports } from "./sandbox/filesystem.mjs";
4
- import { Shell, ShellError, fromExec, quote, quoteArgv } from "./sandbox/shell.mjs";
5
- import { Current, FileSystem, Shell as Shell$1 } from "./sandbox/io.mjs";
4
+ import { i as Shell, n as FileSystem, p as withMutation, r as Mutation, t as Current } from "./io-5PrgzDTe.mjs";
5
+ import { Shell as Shell$1, ShellError, fromExec, quote, quoteArgv } from "./sandbox/shell.mjs";
6
6
  import { AbsolutePath, Name, RuntimeConfigBase, driver, module as defineModule } from "./sandbox/driver.mjs";
7
7
  import { SandboxProviderError, makeRedactor, providerError, providerErrorCause, providerErrorIsNotFound, sanitizeError } from "./sandbox/errors.mjs";
8
8
  import { SandboxResource as resource_exports } from "./sandbox/resource.mjs";
@@ -21,8 +21,10 @@ var driver_exports = /* @__PURE__ */ __exportAll({
21
21
  var io_exports = /* @__PURE__ */ __exportAll({
22
22
  Current: () => Current,
23
23
  FileSystem: () => FileSystem,
24
+ Mutation: () => Mutation,
24
25
  SandboxIO: () => io_exports,
25
- Shell: () => Shell$1
26
+ Shell: () => Shell,
27
+ withMutation: () => withMutation
26
28
  });
27
29
  //#endregion
28
30
  //#region src/sandbox/provider.ts
@@ -37,7 +39,7 @@ var provider_exports = /* @__PURE__ */ __exportAll({
37
39
  //#endregion
38
40
  //#region src/sandbox/public/shell.ts
39
41
  var shell_exports = /* @__PURE__ */ __exportAll({
40
- Shell: () => Shell,
42
+ Shell: () => Shell$1,
41
43
  ShellError: () => ShellError,
42
44
  fromExec: () => fromExec,
43
45
  quote: () => quote,
package/sandbox.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.mjs","names":[],"sources":["../../src/sandbox/public/driver.ts","../../src/sandbox/public/io.ts","../../src/sandbox/provider.ts","../../src/sandbox/public/shell.ts"],"sourcesContent":["export { AbsolutePath, apiVersion, driver, module, Name, RuntimeConfigBase } from \"../driver.ts\";\nexport type {\n\tApiVersion,\n\tCapabilities,\n\tDefinition,\n\tDriver,\n\tModule,\n\tModuleDefinition,\n\tObserved,\n\tProvisioned,\n\tRegistration,\n\tRuntimeConfigBase as RuntimeConfig,\n\tRuntimeInput,\n} from \"../driver.ts\";\n\nexport * as SandboxDriver from \"./driver.ts\";\n","export { Current, FileSystem, Shell } from \"../io.ts\";\nexport type { Identity, Layer, Provides } from \"../io.ts\";\n\nexport * as SandboxIO from \"./io.ts\";\n","export {\n\tmakeRedactor,\n\tproviderError,\n\tproviderErrorCause,\n\tproviderErrorIsNotFound,\n\tSandboxProviderError,\n\tsanitizeError,\n} from \"./errors.ts\";\nexport type { Redactor } from \"./errors.ts\";\n","export { fromExec, quote, quoteArgv, Shell, ShellError } from \"../shell.ts\";\nexport type { ExecChunk, ExecResult, ISandboxExe, ShellOptions } from \"../shell.ts\";\n"],"mappings":""}
1
+ {"version":3,"file":"sandbox.mjs","names":[],"sources":["../../src/sandbox/public/driver.ts","../../src/sandbox/public/io.ts","../../src/sandbox/provider.ts","../../src/sandbox/public/shell.ts"],"sourcesContent":["export { AbsolutePath, apiVersion, driver, module, Name, RuntimeConfigBase } from \"../driver.ts\";\nexport type {\n\tApiVersion,\n\tCapabilities,\n\tDefinition,\n\tDriver,\n\tModule,\n\tModuleDefinition,\n\tObserved,\n\tProvisioned,\n\tRegistration,\n\tRuntimeConfigBase as RuntimeConfig,\n\tRuntimeInput,\n} from \"../driver.ts\";\n\nexport * as SandboxDriver from \"./driver.ts\";\n","export { Current, FileSystem, Mutation, Shell, withMutation } from \"../io.ts\";\nexport type { Identity, Layer, Provides } from \"../io.ts\";\n\nexport * as SandboxIO from \"./io.ts\";\n","export {\n\tmakeRedactor,\n\tproviderError,\n\tproviderErrorCause,\n\tproviderErrorIsNotFound,\n\tSandboxProviderError,\n\tsanitizeError,\n} from \"./errors.ts\";\nexport type { Redactor } from \"./errors.ts\";\n","export { fromExec, quote, quoteArgv, Shell, ShellError } from \"../shell.ts\";\nexport type { ExecChunk, ExecResult, ISandboxExe, ShellOptions } from \"../shell.ts\";\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"io.mjs","names":["SandboxFileSystem.Service","ShellTag","EffectLayer","SandboxFileSystem.withCwd","shellWithCwd"],"sources":["../../../src/sandbox/io.ts"],"sourcesContent":["import { Context, Effect, Layer as EffectLayer } from \"effect\";\nimport { posix } from \"../posix.ts\";\nimport type { SandboxDriver } from \"./driver.ts\";\nimport { SandboxFileSystem } from \"./filesystem.ts\";\nimport { SandboxInstance } from \"./instance.ts\";\nimport { type ISandboxExe, Shell as ShellTag, withCwd as shellWithCwd } from \"./shell.ts\";\n\n/**\n * `SandboxIO` is a **mount**: a filesystem, a shell, and the identity and\n * working directory they act on.\n *\n * It is the whole vocabulary a consumer needs. Project, Git, Copy, Location, and\n * every tool ask for `SandboxIO.FileSystem`, `SandboxIO.Shell`, and\n * `SandboxIO.Current` — never for a driver, an address, or a provider SDK — so\n * a host directory, an in-memory VFS, and a remote microVM are interchangeable\n * behind one contract.\n *\n * The mount neither creates nor destroys infrastructure. `SandboxInstance` is\n * the durable namespace it acts on — a device, which exists whether or not\n * anything has it mounted — and `Sandbox.Controller` is the only path that\n * creates, stops, or destroys one.\n */\n\n/**\n * The filesystem tag. Re-exported here so consumers import one namespace —\n * Project, Git, Copy, and the runner ask for `SandboxIO.FileSystem`, never for\n * the module that happens to define it. Code *inside* `sandbox/` keeps importing\n * the tag directly, since `io.ts` is built on top of it.\n */\nexport const FileSystem = SandboxFileSystem.Service;\nexport type FileSystem = SandboxFileSystem.Service;\n\n/** The shell tag. Re-exported here so consumers import one namespace. */\nexport const Shell = ShellTag;\nexport type Shell = ShellTag;\n\n/**\n * What a mount sees: immutable identity, plus the working directory resolved for\n * *this* mount.\n *\n * Nothing mutable belongs here. `status`, `usage`, and reference counts all\n * change while a mount is open, so a mount-time snapshot of them would be wrong\n * by construction — runtime code that needs live management state asks the\n * control plane. The driver's own resource locator is likewise absent: consumers\n * never parse a Vercel name or a Daytona id.\n */\nexport interface Identity {\n\treadonly id: SandboxInstance.ID;\n\treadonly driver: SandboxDriver.Name;\n\treadonly kind: SandboxInstance.Kind;\n\t/** Absolute, and always a path in *this* namespace. */\n\treadonly cwd: string;\n}\n\n/** Identity and working directory of the current mount. */\nexport class Current extends Context.Service<Current, Identity>()(\"@codeworksh/plugin/sandbox/io/Current\") {}\n\n/** Everything a mount provides. */\nexport type Provides = Current | SandboxFileSystem.Service | ShellTag;\n\n/** A built mount. */\nexport type Layer<E = never, RIn = never> = EffectLayer.Layer<Provides, E, RIn>;\n\n/**\n * Resolve a mount's cwd without consulting ambient process state.\n *\n * The default is supplied by the namespace adapter:\n * provider metadata remotely, `/` for a virtual filesystem, and `process.cwd()` for the host adapter.\n * An explicit absolute cwd replaces it; a relative cwd is resolved inside it. The\n * result is therefore always the one concrete absolute path `Current` requires.\n *\n * A non-absolute default throws rather than failing typed. It is the one\n * defect-level guard in this module, and deliberately so:\n * Adapters reading a value from a provider call this inside their own error channel,\n * where the throw becomes their typed failure (see `EnvDaytona.mountCwd`).\n */\nexport const resolveMountCwd = (defaultCwd: string, cwd?: string): string => {\n\tif (!posix.isAbsolute(defaultCwd)) {\n\t\tthrow new TypeError(`Sandbox default cwd must be absolute: ${defaultCwd}`);\n\t}\n\t// `resolve`, not `normalize`: normalize keeps a trailing slash, and `cwd` is\n\t// persisted — `space.location` and its id hash would read\n\t// `/workspace/` and `/workspace` as two directories and keep a row for each.\n\t//\n\t// A provider-reported default (`getWorkDir()`) or a config value is free to\n\t// carry one, so it is stripped here rather than at every reader.\n\tif (cwd === undefined) return posix.resolve(defaultCwd);\n\treturn posix.isAbsolute(cwd) ? posix.resolve(cwd) : posix.resolve(defaultCwd, cwd);\n};\n\n/**\n * Bind a cwd-neutral transport to one mount.\n *\n * The transport underneath is shared between\n * mounts and stays rooted at the namespace root, and everything directory-shaped\n * happens here, once per mount. Two mounts of one namespace at different working\n * directories therefore coexist without seeing or moving each other's.\n *\n * It consumes the same two tags it provides — the transport is supplied by the\n * layer this is composed over, not by itself.\n */\nexport const mount = (identity: Identity): EffectLayer.Layer<Provides, never, SandboxFileSystem.Service | ShellTag> =>\n\tEffectLayer.mergeAll(\n\t\tEffectLayer.succeed(Current, identity),\n\t\tEffectLayer.effect(\n\t\t\tSandboxFileSystem.Service,\n\t\t\tEffect.map(SandboxFileSystem.Service, (fs) => SandboxFileSystem.withCwd(fs, identity.cwd)),\n\t\t),\n\t\tEffectLayer.effect(\n\t\t\tShellTag,\n\t\t\tEffect.map(ShellTag, (shell: ISandboxExe) => shellWithCwd(shell, identity.cwd)),\n\t\t),\n\t);\n\n/**\n * Just the identity tag, with no filesystem or shell beneath it. For consumers\n * assembled from stubs — a test that runs `Project` over a fake filesystem still\n * needs to know which namespace it is in.\n */\nexport const identityLayer = (identity: Identity) => EffectLayer.succeed(Current, identity);\n\n/** The host identity alone. See {@link identityLayer}. */\nexport const hostLayer = (cwd: string) => identityLayer(host(cwd));\n\n/**\n * The host, rooted at `cwd`. Always `SandboxInstance.ID.local`: the working\n * directory selects where relative paths resolve, it does not make a second host\n * namespace — two mounts rooted at different directories still agree on absolute\n * paths.\n *\n * The host coordinate is explicit so a caller cannot accidentally substitute ambient process\n * state for the application or session directory it owns.\n */\nexport const host = (cwd: string): Identity => ({\n\tid: SandboxInstance.ID.local,\n\tdriver: \"local\" as SandboxDriver.Name,\n\tkind: \"local\",\n\tcwd: resolveMountCwd(cwd),\n});\n\n/**\n * A VFS-backed namespace. The id is minted per call unless one is named, because\n * building one of these builds a fresh VFS: N unnamed calls are N distinct\n * namespaces, none of which outlives the process. A file-backed store is the\n * exception — its file is the state, so whoever knows the file supplies the id\n * it was registered under.\n */\nexport const virtual = (input: {\n\treadonly driver: string;\n\treadonly id?: SandboxInstance.ID;\n\treadonly defaultCwd?: string;\n\treadonly cwd?: string;\n}): Identity => ({\n\tid: input.id ?? SandboxInstance.ID.create(),\n\tdriver: input.driver as SandboxDriver.Name,\n\tkind: \"virtual\",\n\tcwd: resolveMountCwd(input.defaultCwd ?? \"/\", input.cwd),\n});\n\n/**\n * A provider-hosted namespace. The id is always supplied: a remote resource's\n * durable identity is minted and recorded by whoever provisioned it, never\n * derived here from the provider's own locator.\n */\nexport const remote = (input: {\n\treadonly driver: string;\n\treadonly id: SandboxInstance.ID;\n\t/** Namespace-intrinsic default supplied or discovered by the driver. */\n\treadonly defaultCwd: string;\n\treadonly cwd?: string;\n}): Identity => ({\n\tid: input.id,\n\tdriver: input.driver as SandboxDriver.Name,\n\tkind: \"remote\",\n\tcwd: resolveMountCwd(input.defaultCwd, input.cwd),\n});\n\nexport * as SandboxIO from \"./io.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,aAAaA;;AAI1B,MAAa,QAAQC;;AAsBrB,IAAa,UAAb,cAA6B,QAAQ,QAA2B,CAAC,CAAC,uCAAuC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;AAqB5G,MAAa,mBAAmB,YAAoB,QAAyB;CAC5E,IAAI,CAAC,MAAM,WAAW,UAAU,GAC/B,MAAM,IAAI,UAAU,yCAAyC,YAAY;CAQ1E,IAAI,QAAQ,KAAA,GAAW,OAAO,MAAM,QAAQ,UAAU;CACtD,OAAO,MAAM,WAAW,GAAG,IAAI,MAAM,QAAQ,GAAG,IAAI,MAAM,QAAQ,YAAY,GAAG;AAClF;;;;;;;;;;;;AAaA,MAAa,SAAS,aACrBC,MAAY,SACXA,MAAY,QAAQ,SAAS,QAAQ,GACrCA,MAAY,OACXF,SACA,OAAO,IAAIA,UAA4B,OAAOG,QAA0B,IAAI,SAAS,GAAG,CAAC,CAC1F,GACAD,MAAY,OACXD,SACA,OAAO,IAAIA,UAAW,UAAuBG,UAAa,OAAO,SAAS,GAAG,CAAC,CAC/E,CACD;;;;;;AAOD,MAAa,iBAAiB,aAAuBF,MAAY,QAAQ,SAAS,QAAQ;;AAG1F,MAAa,aAAa,QAAgB,cAAc,KAAK,GAAG,CAAC;;;;;;;;;;AAWjE,MAAa,QAAQ,SAA2B;CAC/C,IAAA,GAAuB;CACvB,QAAQ;CACR,MAAM;CACN,KAAK,gBAAgB,GAAG;AACzB;;;;;;;;AASA,MAAa,WAAW,WAKP;CAChB,IAAI,MAAM,MAAA,GAAyB,OAAO;CAC1C,QAAQ,MAAM;CACd,MAAM;CACN,KAAK,gBAAgB,MAAM,cAAc,KAAK,MAAM,GAAG;AACxD;;;;;;AAOA,MAAa,UAAU,WAMN;CAChB,IAAI,MAAM;CACV,QAAQ,MAAM;CACd,MAAM;CACN,KAAK,gBAAgB,MAAM,YAAY,MAAM,GAAG;AACjD"}