@demicodes/shell 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ import { u as HostStore } from "./host-BfjoIvF3.mjs";
2
+ import { z } from "zod";
3
+
4
+ //#region src/command.d.ts
5
+ type CommandInputSpec = Record<string, z.ZodType>;
6
+ /**
7
+ * A command is a tree of arbitrary depth, matching standard CLI semantics
8
+ * (cobra/click): group nodes (`CommandSpec`) route and render help, leaf nodes
9
+ * (`CommandSubcommandSpec`) carry the input schema and the executable. The
10
+ * registry registers root groups; `<path...> prompt` renders help at any group.
11
+ */
12
+ interface CommandSpec {
13
+ name: string;
14
+ summary: string;
15
+ subcommands: CommandNode[];
16
+ }
17
+ type CommandNode = CommandSpec | CommandSubcommandSpec;
18
+ declare function isCommandGroup(node: CommandNode): node is CommandSpec;
19
+ interface CommandSubcommandSpec {
20
+ name: string;
21
+ summary: string;
22
+ effects?: string;
23
+ successOutput?: string;
24
+ failureOutput?: string;
25
+ input?: CommandInputSpec;
26
+ positionals?: string[];
27
+ stdinField?: string;
28
+ output?: CommandOutputSpec;
29
+ examples: string[];
30
+ run(ctx: CommandRunContext): Promise<CommandRunResult> | CommandRunResult;
31
+ }
32
+ interface CommandOutputSpec {
33
+ json?: z.ZodType;
34
+ }
35
+ interface ParsedCommandInput {
36
+ /** Leaf subcommand name, or 'prompt' for the help pseudo-subcommand. */
37
+ subcommand: string;
38
+ /**
39
+ * Segments after the root command name: group names down to the leaf. For
40
+ * 'prompt' it is the path of the group the help applies to (empty = root).
41
+ */
42
+ path: string[];
43
+ values: Record<string, unknown>;
44
+ json: boolean;
45
+ }
46
+ interface CommandRunContext {
47
+ argv: string[];
48
+ parsed: ParsedCommandInput;
49
+ stdin: CommandStdin;
50
+ env: Record<string, string>;
51
+ cwd: string;
52
+ io: CommandIO;
53
+ storage: CommandStorage;
54
+ }
55
+ interface CommandRunResult {
56
+ exitCode: number;
57
+ metadata?: unknown;
58
+ }
59
+ interface CommandStdin {
60
+ text: string;
61
+ }
62
+ /** A non-text content item a command emits to the model, peer to stdout text. */
63
+ type CommandAsset = {
64
+ type: 'image';
65
+ mediaType: string;
66
+ data: string;
67
+ };
68
+ interface CommandIO {
69
+ stdout(data: string | Uint8Array): Promise<void> | void;
70
+ stderr(data: string | Uint8Array): Promise<void> | void;
71
+ asset(asset: CommandAsset): Promise<void> | void;
72
+ }
73
+ interface CommandStorage {
74
+ readJson<T>(key: string): Promise<T | null>;
75
+ writeJson<T>(key: string, value: T): Promise<void>;
76
+ delete(key: string): Promise<void>;
77
+ list(prefix: string): Promise<string[]>;
78
+ }
79
+ interface CommandExecutionContext {
80
+ argv: string[];
81
+ stdin?: CommandStdin;
82
+ env: Record<string, string>;
83
+ cwd: string;
84
+ io: CommandIO;
85
+ storage: CommandStorage;
86
+ }
87
+ declare class CommandRegistry {
88
+ private readonly commands;
89
+ register(spec: CommandSpec): void;
90
+ get(name: string): CommandSpec | null;
91
+ list(): CommandSpec[];
92
+ renderPrompt(): string;
93
+ }
94
+ declare const COMMAND_PROMPT_DEFAULTS = "Unless a subcommand states otherwise: success prints raw text on stdout, failure writes an error message to stderr and exits non-zero.";
95
+ declare function parseCommandInput(spec: CommandSpec, argv: string[], stdin?: CommandStdin): ParsedCommandInput;
96
+ declare function runRegisteredCommand(spec: CommandSpec, ctx: CommandExecutionContext): Promise<CommandRunResult>;
97
+ declare function renderCommandPrompt(spec: CommandSpec, parentPath?: string): string;
98
+ //#endregion
99
+ //#region src/storage.d.ts
100
+ declare class AgentSessionCommandStorage implements CommandStorage {
101
+ private readonly store;
102
+ private readonly agentSessionPrefix;
103
+ constructor(store: HostStore, agentSessionId: string);
104
+ readJson<T>(key: string): Promise<T | null>;
105
+ writeJson<T>(key: string, value: T): Promise<void>;
106
+ delete(key: string): Promise<void>;
107
+ list(prefix: string): Promise<string[]>;
108
+ private key;
109
+ }
110
+ //#endregion
111
+ export { isCommandGroup as _, CommandIO as a, runRegisteredCommand as b, CommandOutputSpec as c, CommandRunResult as d, CommandSpec as f, ParsedCommandInput as g, CommandSubcommandSpec as h, CommandExecutionContext as i, CommandRegistry as l, CommandStorage as m, COMMAND_PROMPT_DEFAULTS as n, CommandInputSpec as o, CommandStdin as p, CommandAsset as r, CommandNode as s, AgentSessionCommandStorage as t, CommandRunContext as u, parseCommandInput as v, renderCommandPrompt as y };
@@ -0,0 +1,2 @@
1
+ import { t as AgentSessionCommandStorage } from "./storage-DJxxqyZA.mjs";
2
+ export { AgentSessionCommandStorage };
@@ -0,0 +1,37 @@
1
+ //#region src/storage.ts
2
+ var AgentSessionCommandStorage = class {
3
+ store;
4
+ agentSessionPrefix;
5
+ constructor(store, agentSessionId) {
6
+ this.store = store;
7
+ validateAgentSessionId(agentSessionId);
8
+ this.agentSessionPrefix = `${agentSessionId}/`;
9
+ }
10
+ readJson(key) {
11
+ return this.store.readJson(this.key(key));
12
+ }
13
+ writeJson(key, value) {
14
+ return this.store.writeJson(this.key(key), value);
15
+ }
16
+ delete(key) {
17
+ return this.store.delete(this.key(key));
18
+ }
19
+ async list(prefix) {
20
+ const scopedPrefix = this.key(prefix);
21
+ return (await this.store.list(scopedPrefix)).map((key) => key.startsWith(this.agentSessionPrefix) ? key.slice(this.agentSessionPrefix.length) : key);
22
+ }
23
+ key(key) {
24
+ validateStorageKey(key);
25
+ return `${this.agentSessionPrefix}${key}`;
26
+ }
27
+ };
28
+ function validateAgentSessionId(agentSessionId) {
29
+ if (!agentSessionId || agentSessionId.includes("\0") || /[\\/]/.test(agentSessionId) || agentSessionId === "." || agentSessionId === "..") throw new Error(`Invalid command storage agent session id: ${agentSessionId}`);
30
+ }
31
+ function validateStorageKey(key) {
32
+ if (key.includes("\0")) throw new Error(`Invalid CommandStorage key: ${key}`);
33
+ if (key.startsWith("/") || /^[A-Za-z]:[\\/]/.test(key)) throw new Error(`CommandStorage keys must be relative: ${key}`);
34
+ for (const segment of key.split(/[\\/]+/)) if (segment === "..") throw new Error(`CommandStorage keys must not contain path traversal: ${key}`);
35
+ }
36
+ //#endregion
37
+ export { AgentSessionCommandStorage };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@demicodes/shell",
3
+ "description": "Sandboxable bash engine and Host contract for Demi.",
4
+ "version": "0.1.0",
5
+ "private": false,
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "development": "./src/index.ts",
10
+ "types": "./dist/index.d.mts",
11
+ "import": "./dist/index.mjs"
12
+ },
13
+ "./storage": {
14
+ "development": "./src/storage.ts",
15
+ "types": "./dist/storage.d.mts",
16
+ "import": "./dist/storage.mjs"
17
+ },
18
+ "./host-fs": {
19
+ "development": "./src/host-fs.ts",
20
+ "types": "./dist/host-fs.d.mts",
21
+ "import": "./dist/host-fs.mjs"
22
+ }
23
+ },
24
+ "dependencies": {
25
+ "@demicodes/utils": "workspace:*",
26
+ "@demicodes/just-bash": "workspace:*",
27
+ "zod": "^4.0.0"
28
+ },
29
+ "license": "Apache-2.0",
30
+ "main": "./dist/index.mjs",
31
+ "module": "./dist/index.mjs",
32
+ "types": "./dist/index.d.mts",
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsdown"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/wspl/demi.git",
45
+ "directory": "packages/shell"
46
+ },
47
+ "homepage": "https://github.com/wspl/demi/tree/main/packages/shell#readme",
48
+ "bugs": "https://github.com/wspl/demi/issues"
49
+ }