@demicodes/shell 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -72,6 +72,11 @@ interface HostFileSystem {
72
72
  interface HostProcess {
73
73
  spawn(params: HostSpawnParams): Promise<HostSpawnHandle>;
74
74
  }
75
+ /**
76
+ * Keyed JSON state storage. Implementations must round-trip `Uint8Array` and
77
+ * `bigint` values (e.g. via the portable JSON codec in `@demicodes/utils`),
78
+ * since stored values such as agent session snapshots carry binary content.
79
+ */
75
80
  interface HostStore {
76
81
  readJson<T>(key: string): Promise<T | null>;
77
82
  writeJson<T>(key: string, value: T): Promise<void>;
@@ -1,6 +1,5 @@
1
- import { t as Host } from "./host-BfjoIvF3.mjs";
1
+ import { t as Host } from "./host-DIg4RxcL.mjs";
2
2
  import { BufferEncoding, CpOptions, DirentEntry, FileContent, FsStat, IFileSystem, MkdirOptions, ReadFileOptions, RmOptions, WriteFileOptions } from "@demicodes/just-bash/fs/interface";
3
-
4
3
  //#region src/host-fs.d.ts
5
4
  type VirtualFileSystemNode = {
6
5
  kind: 'file';
package/dist/host-fs.mjs CHANGED
@@ -166,13 +166,13 @@ function encodingFrom(options) {
166
166
  function encodeContent(content, encoding) {
167
167
  if (content instanceof Uint8Array) return content;
168
168
  if (encoding === "binary" || encoding === "latin1") return latin1ToBytes(content);
169
- if (encoding === "base64") return base64ToBytes(content);
169
+ if (encoding === "base64") return base64ToBytes$1(content);
170
170
  if (encoding === "hex") return hexToBytes(content);
171
171
  return encodeUtf8(content);
172
172
  }
173
173
  function decodeBytes(bytes, encoding) {
174
174
  if (encoding === "binary" || encoding === "latin1") return bytesToLatin1(bytes);
175
- if (encoding === "base64") return bytesToBase64(bytes);
175
+ if (encoding === "base64") return bytesToBase64$1(bytes);
176
176
  if (encoding === "hex") return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
177
177
  return decodeUtf8(bytes);
178
178
  }
@@ -186,10 +186,10 @@ function bytesToLatin1(bytes) {
186
186
  for (let index = 0; index < bytes.length; index += 8192) result += String.fromCharCode(...bytes.subarray(index, index + 8192));
187
187
  return result;
188
188
  }
189
- function base64ToBytes(content) {
189
+ function base64ToBytes$1(content) {
190
190
  return latin1ToBytes(atob(content));
191
191
  }
192
- function bytesToBase64(bytes) {
192
+ function bytesToBase64$1(bytes) {
193
193
  return btoa(bytesToLatin1(bytes));
194
194
  }
195
195
  function hexToBytes(content) {
package/dist/index.d.mts CHANGED
@@ -1,40 +1,15 @@
1
- import { a as HostProcess, c as HostSpawnHandle, i as HostFileSystem, l as HostSpawnParams, n as HostDirent, o as HostProcessOutputChunk, r as HostFileStat, s as HostSpawnExit, t as Host, u as HostStore } from "./host-BfjoIvF3.mjs";
1
+ import { a as HostProcess, c as HostSpawnHandle, i as HostFileSystem, l as HostSpawnParams, n as HostDirent, o as HostProcessOutputChunk, r as HostFileStat, s as HostSpawnExit, t as Host, u as HostStore } from "./host-DIg4RxcL.mjs";
2
2
  import { HostBackedFileSystem, VirtualFileSystemNode, VirtualFileSystemProvider, virtualDirectory, virtualFile } from "./host-fs.mjs";
3
- import { _ as isCommandGroup, a as CommandIO, b as runRegisteredCommand, c as CommandOutputSpec, d as CommandRunResult, f as CommandSpec, g as ParsedCommandInput, h as CommandSubcommandSpec, i as CommandExecutionContext, l as CommandRegistry, m as CommandStorage, n as COMMAND_PROMPT_DEFAULTS, o as CommandInputSpec, p as CommandStdin, r as CommandAsset, s as CommandNode, t as AgentSessionCommandStorage, u as CommandRunContext, v as parseCommandInput, y as renderCommandPrompt } from "./storage-DJxxqyZA.mjs";
4
- import { Interpreter, InterpreterState } from "@demicodes/just-bash/interpreter";
3
+ import { _ as runRegisteredCommand, a as CommandIO, c as CommandRegistry, d as CommandStdin, f as CommandStorage, g as renderCommandHelp, h as parseCommandInput, i as CommandExecutionContext, l as CommandRunContext, m as emptyStdin, n as COMMAND_HELP_DEFAULTS, o as CommandInputSpec, p as ParsedCommandInput, r as Command, s as CommandOutputSpec, t as AgentSessionCommandStorage, u as CommandRunResult } from "./storage-MeB35Df6.mjs";
5
4
  import { CommandName } from "@demicodes/just-bash/commands";
5
+ import { Interpreter, InterpreterState } from "@demicodes/just-bash/interpreter";
6
6
  import { CommandRegistry as CommandRegistry$1, ExecResult } from "@demicodes/just-bash/types";
7
-
8
- //#region src/command-projection.d.ts
9
- /**
10
- * A registered command leaf described as a structured operation: the second
11
- * projection of a CommandSpec. The shell invocation (argv + heredoc) and this
12
- * form share one implementation — `renderScript` produces a script that runs
13
- * through the normal BashEnvironment path, so audit, command records, and
14
- * `/@/commands` artifacts behave identically for both projections.
15
- */
16
- interface RegisteredCommandOperation {
17
- /** Path segments from root command to leaf, e.g. ['editor', 'create']. */
18
- path: string[];
19
- description: string;
20
- /** JSON Schema for the operation input, derived from the leaf's zod spec. */
21
- inputSchema: Record<string, unknown>;
22
- /**
23
- * Renders a shell script invoking this operation with the given input.
24
- * The stdin field (if any) is delivered as a quoted heredoc, which — like
25
- * any heredoc — normalizes the body to end with a newline.
26
- */
27
- renderScript(values: Record<string, unknown>): string;
28
- }
29
- declare function listRegisteredCommandOperations(commands: CommandRegistry | CommandSpec[]): RegisteredCommandOperation[];
30
- //#endregion
31
7
  //#region src/environment-state.d.ts
32
8
  interface ExecAccumulator {
33
9
  stdout: string;
34
10
  stderr: string;
35
11
  audit: BashAuditEvent[];
36
12
  commandMetadata: CommandMetadataRecord[];
37
- assets: CommandAsset[];
38
13
  }
39
14
  interface ShellSession {
40
15
  id: string;
@@ -80,6 +55,8 @@ interface ForegroundProcess {
80
55
  /** Everything the process wrote, including redirected output — this is what
81
56
  * the interpreter observes as the command's stdout/stderr. */
82
57
  rawStdoutBuffer: string;
58
+ /** Raw stdout byte chunks for byte-clean pipeline continuation. */
59
+ rawStdoutBytes: Uint8Array[];
83
60
  rawStderrBuffer: string;
84
61
  /** Output routed to the visible sinks only (redirections excluded) — this is
85
62
  * what command records and model previews show. */
@@ -130,6 +107,18 @@ interface ShellExecInput {
130
107
  timeoutMs?: number;
131
108
  maxOutputBytes?: number;
132
109
  signal?: AbortSignal;
110
+ /**
111
+ * Run in a dedicated one-shot shell instead of the session default shell, so
112
+ * cd/env side effects never leak into other execs sharing the session. The
113
+ * caller owns the shell and should `disposeShell(snapshot.shellId)` when done.
114
+ * Mutually exclusive with `shellId`.
115
+ */
116
+ ephemeral?: boolean;
117
+ /**
118
+ * Initial working directory of the shell this exec creates. Requires
119
+ * `ephemeral` — a persistent shell owns its cwd (that is what `cd` is for).
120
+ */
121
+ cwd?: string;
133
122
  }
134
123
  interface ShellStatusInput {
135
124
  commandId: string;
@@ -197,6 +186,14 @@ interface CommandMetadataRecord {
197
186
  args: string[];
198
187
  metadata: unknown;
199
188
  }
189
+ /** Final stdout stream that is not valid UTF-8: raw bytes for the boundary above. */
190
+ interface BinaryStdout {
191
+ data: Uint8Array;
192
+ /** True when the stream exceeded the exec's output limit; data is capped. */
193
+ truncated: boolean;
194
+ /** Total byte count of the un-capped stream. */
195
+ totalBytes: number;
196
+ }
200
197
  type ShellCommandSnapshot = {
201
198
  status: 'exited';
202
199
  shellId: string;
@@ -209,7 +206,8 @@ type ShellCommandSnapshot = {
209
206
  idleMs: number;
210
207
  audit: BashAuditEvent[];
211
208
  commandMetadata?: CommandMetadataRecord[];
212
- assets?: CommandAsset[];
209
+ /** Present when the final stream was binary (bytes that are not valid UTF-8). */
210
+ binaryStdout?: BinaryStdout;
213
211
  } | {
214
212
  status: 'running';
215
213
  shellId: string;
@@ -229,6 +227,8 @@ type ShellCommandSnapshot = {
229
227
  runningMs: number;
230
228
  idleMs: number;
231
229
  };
230
+ /** Upper bound for a single exec observation window (also the command-bridge wait ceiling). */
231
+ declare const MAX_TIMEOUT_MS = 600000;
232
232
  declare class BashEnvironment {
233
233
  private readonly host;
234
234
  private readonly commands;
@@ -243,8 +243,8 @@ declare class BashEnvironment {
243
243
  private readonly artifacts;
244
244
  constructor(options: BashEnvironmentOptions);
245
245
  getShell(shellId: string): ShellSession | null;
246
- registerCommand(spec: CommandSpec): void;
247
- registeredCommands(): CommandSpec[];
246
+ registerCommand(command: Command): void;
247
+ registeredCommands(): Command[];
248
248
  exec(input: ShellExecInput): Promise<ShellCommandSnapshot>;
249
249
  status(input: ShellStatusInput): Promise<ShellCommandSnapshot>;
250
250
  write(input: ShellWriteInput): Promise<ShellCommandSnapshot>;
@@ -284,6 +284,18 @@ declare class BashEnvironment {
284
284
  /**
285
285
  * Fork portable commands BashEnvironment registers in every shell, so
286
286
  * cat/ls/grep-class tools work without local coreutils on any Host backend.
287
+ *
288
+ * Sourced directly from just-bash's own registry instead of a hand-maintained
289
+ * copy: `CommandName` is just-bash's own "safe to run anywhere" set — it
290
+ * already excludes the commands that need real process/network access
291
+ * (curl → NetworkCommandName, python3/python → PythonCommandName, js-exec/node
292
+ * → JavaScriptCommandName all live in separate, non-portable type unions). A
293
+ * hand-picked subset of this list drifts silently as just-bash adds commands
294
+ * (this one was missing echo, pwd, printf, date, env, hostname, whoami, gzip,
295
+ * tar, split, sqlite3, xan, and more — all already categorized as safe
296
+ * upstream, just never backported here). Deriving it removes that drift
297
+ * entirely: everything just-bash calls portable (minus the exceptions above),
298
+ * we call portable.
287
299
  */
288
300
  declare const DEMI_PORTABLE_COMMANDS: readonly CommandName[];
289
301
  /**
@@ -293,4 +305,10 @@ declare const DEMI_PORTABLE_COMMANDS: readonly CommandName[];
293
305
  */
294
306
  declare const RESERVED_COMMAND_NAMES: ReadonlySet<string>;
295
307
  //#endregion
296
- export { AgentSessionCommandStorage, BashAuditEvent, BashEnvironment, BashEnvironmentOptions, COMMAND_PROMPT_DEFAULTS, CommandAsset, CommandExecutionContext, CommandIO, CommandInputSpec, CommandMetadataRecord, CommandNode, CommandOutputSpec, CommandRegistry, CommandRunContext, CommandRunResult, CommandSpec, CommandStdin, CommandStorage, CommandSubcommandSpec, DEMI_PORTABLE_COMMANDS, Host, HostBackedFileSystem, HostDirent, HostFileStat, HostFileSystem, HostProcess, HostProcessOutputChunk, HostSpawnExit, HostSpawnHandle, HostSpawnParams, HostStore, ParsedCommandInput, RESERVED_COMMAND_NAMES, RegisteredCommandOperation, ShellAbortInput, ShellCommandSnapshot, ShellExecInput, ShellOutputArtifact, ShellOutputChunk, ShellOutputRecordChunk, ShellStatusInput, ShellWriteInput, StreamArtifact, VirtualFileSystemNode, VirtualFileSystemProvider, isCommandGroup, listRegisteredCommandOperations, parseCommandInput, renderCommandPrompt, runRegisteredCommand, virtualDirectory, virtualFile };
308
+ //#region src/shell-quote.d.ts
309
+ /** Single-quotes a value for safe use as one shell word. */
310
+ declare function shellQuote(value: string): string;
311
+ /** Picks a heredoc delimiter that does not collide with any line already in `body`. */
312
+ declare function heredocDelimiter(body: string): string;
313
+ //#endregion
314
+ export { AgentSessionCommandStorage, BashAuditEvent, BashEnvironment, BashEnvironmentOptions, BinaryStdout, COMMAND_HELP_DEFAULTS, Command, CommandExecutionContext, CommandIO, CommandInputSpec, CommandMetadataRecord, CommandOutputSpec, CommandRegistry, CommandRunContext, CommandRunResult, CommandStdin, CommandStorage, DEMI_PORTABLE_COMMANDS, Host, HostBackedFileSystem, HostDirent, HostFileStat, HostFileSystem, HostProcess, HostProcessOutputChunk, HostSpawnExit, HostSpawnHandle, HostSpawnParams, HostStore, MAX_TIMEOUT_MS, ParsedCommandInput, RESERVED_COMMAND_NAMES, ShellAbortInput, ShellCommandSnapshot, ShellExecInput, ShellOutputArtifact, ShellOutputChunk, ShellOutputRecordChunk, ShellStatusInput, ShellWriteInput, StreamArtifact, VirtualFileSystemNode, VirtualFileSystemProvider, emptyStdin, heredocDelimiter, parseCommandInput, renderCommandHelp, runRegisteredCommand, shellQuote, virtualDirectory, virtualFile };