inhuman 0.1.0 → 0.3.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.
Files changed (91) hide show
  1. package/README.md +49 -0
  2. package/bin/inhuman.mjs +2 -20
  3. package/dist/bin.d.ts +6 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +16 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/cli/blobs-command.d.ts +31 -0
  8. package/dist/cli/blobs-command.d.ts.map +1 -0
  9. package/dist/cli/blobs-command.js +184 -0
  10. package/dist/cli/blobs-command.js.map +1 -0
  11. package/dist/cli/browser.d.ts +3 -0
  12. package/dist/cli/browser.d.ts.map +1 -0
  13. package/dist/cli/browser.js +10 -0
  14. package/dist/cli/browser.js.map +1 -0
  15. package/dist/cli/completion-command.d.ts +15 -0
  16. package/dist/cli/completion-command.d.ts.map +1 -0
  17. package/dist/cli/completion-command.js +201 -0
  18. package/dist/cli/completion-command.js.map +1 -0
  19. package/dist/cli/context.d.ts +23 -0
  20. package/dist/cli/context.d.ts.map +1 -0
  21. package/dist/cli/context.js +67 -0
  22. package/dist/cli/context.js.map +1 -0
  23. package/dist/cli/daemon.d.ts +22 -0
  24. package/dist/cli/daemon.d.ts.map +1 -0
  25. package/dist/cli/daemon.js +61 -0
  26. package/dist/cli/daemon.js.map +1 -0
  27. package/dist/cli/eval-command.d.ts +16 -0
  28. package/dist/cli/eval-command.d.ts.map +1 -0
  29. package/dist/cli/eval-command.js +114 -0
  30. package/dist/cli/eval-command.js.map +1 -0
  31. package/dist/cli/install-command.d.ts +8 -0
  32. package/dist/cli/install-command.d.ts.map +1 -0
  33. package/dist/cli/install-command.js +25 -0
  34. package/dist/cli/install-command.js.map +1 -0
  35. package/dist/cli/kernel-client.d.ts +3 -0
  36. package/dist/cli/kernel-client.d.ts.map +1 -0
  37. package/dist/cli/kernel-client.js +12 -0
  38. package/dist/cli/kernel-client.js.map +1 -0
  39. package/dist/cli/mcp-commands.d.ts +61 -0
  40. package/dist/cli/mcp-commands.d.ts.map +1 -0
  41. package/dist/cli/mcp-commands.js +139 -0
  42. package/dist/cli/mcp-commands.js.map +1 -0
  43. package/dist/cli/mcp.d.ts +25 -0
  44. package/dist/cli/mcp.d.ts.map +1 -0
  45. package/dist/cli/mcp.js +261 -0
  46. package/dist/cli/mcp.js.map +1 -0
  47. package/dist/cli/register.d.ts +12 -0
  48. package/dist/cli/register.d.ts.map +1 -0
  49. package/dist/cli/register.js +133 -0
  50. package/dist/cli/register.js.map +1 -0
  51. package/dist/cli/remote-commands.d.ts +49 -0
  52. package/dist/cli/remote-commands.d.ts.map +1 -0
  53. package/dist/cli/remote-commands.js +184 -0
  54. package/dist/cli/remote-commands.js.map +1 -0
  55. package/dist/cli/resume-complete.d.ts +24 -0
  56. package/dist/cli/resume-complete.d.ts.map +1 -0
  57. package/dist/cli/resume-complete.js +35 -0
  58. package/dist/cli/resume-complete.js.map +1 -0
  59. package/dist/cli/shell-import.d.ts +22 -0
  60. package/dist/cli/shell-import.d.ts.map +1 -0
  61. package/dist/cli/shell-import.js +32 -0
  62. package/dist/cli/shell-import.js.map +1 -0
  63. package/dist/cli/tui-command.d.ts +11 -0
  64. package/dist/cli/tui-command.d.ts.map +1 -0
  65. package/dist/cli/tui-command.js +41 -0
  66. package/dist/cli/tui-command.js.map +1 -0
  67. package/dist/cli/web-commands.d.ts +54 -0
  68. package/dist/cli/web-commands.d.ts.map +1 -0
  69. package/dist/cli/web-commands.js +106 -0
  70. package/dist/cli/web-commands.js.map +1 -0
  71. package/dist/cli/web-door-command.d.ts +11 -0
  72. package/dist/cli/web-door-command.d.ts.map +1 -0
  73. package/dist/cli/web-door-command.js +151 -0
  74. package/dist/cli/web-door-command.js.map +1 -0
  75. package/dist/cli/web-door.d.ts +25 -0
  76. package/dist/cli/web-door.d.ts.map +1 -0
  77. package/dist/cli/web-door.js +116 -0
  78. package/dist/cli/web-door.js.map +1 -0
  79. package/dist/cli/web-static.d.ts +8 -0
  80. package/dist/cli/web-static.d.ts.map +1 -0
  81. package/dist/cli/web-static.js +23 -0
  82. package/dist/cli/web-static.js.map +1 -0
  83. package/dist/eval/progress.d.ts +8 -0
  84. package/dist/eval/progress.d.ts.map +1 -0
  85. package/dist/eval/progress.js +64 -0
  86. package/dist/eval/progress.js.map +1 -0
  87. package/dist/eval/run.d.ts +20 -0
  88. package/dist/eval/run.d.ts.map +1 -0
  89. package/dist/eval/run.js +301 -0
  90. package/dist/eval/run.js.map +1 -0
  91. package/package.json +42 -5
@@ -0,0 +1,184 @@
1
+ /**
2
+ * `inhuman login | logout | remote status`: remote access through the relay.
3
+ * The daemon does the work (`remote/login`, `remote/logout`, `remote/status`); this renders the parked
4
+ * open-url form and the status. The daemon reads HARNESS_REMOTE_URL (and the optional
5
+ * HARNESS_REMOTE_WORKOS_CLIENT_ID override) from its own environment, inherited from the process that spawned it.
6
+ */
7
+ import { isUiForm } from "@inhuman.tools/harness-contract";
8
+ import { openExternalUrl } from "@inhuman.tools/harness-sdk";
9
+ import { Command, Option } from "clipanion";
10
+ import { KernelCommand } from "./context.js";
11
+ import { openKernelRpc } from "./kernel-client.js";
12
+ import { ensureServing, parsePort, realServeDeps, serveOutput, webShellInstalled } from "./web-commands.js";
13
+ const ENV_HELP = `
14
+ The daemon reads two optional variables from its own environment, so set them before it starts (run
15
+ \`inhuman daemon restart\` if it is already running):
16
+
17
+ HARNESS_REMOTE_URL relay origin (default https://harness.inhuman.tools)
18
+ HARNESS_REMOTE_WORKOS_CLIENT_ID WorkOS client id (default: the one the relay publishes)
19
+ `;
20
+ export class LoginCommand extends KernelCommand {
21
+ static paths = [["login"]];
22
+ static usage = Command.Usage({
23
+ category: "Remote",
24
+ description: "start the daemon and web server if needed, then sign this machine in for remote access",
25
+ details: `
26
+ Runs \`inhuman start\` first, so the daemon and the web server are up. Starts a WorkOS device login. Open the printed address, check the code, and approve. The daemon then keeps
27
+ a connection to the relay open and this machine shows up on the remote picker.
28
+ ${ENV_HELP}`,
29
+ examples: [["Name the machine", "$0 login --name laptop"]],
30
+ });
31
+ name = Option.String("--name", { description: "machine name on the remote picker (default: hostname)" });
32
+ browser = Option.Boolean("--browser", true, { description: "open the approval page in a browser" });
33
+ port = Option.String("--port", "8787", { description: "preferred loopback port for the web server" });
34
+ async execute() {
35
+ const blocked = this.rejectUnsupportedAgentFlags("inhuman login");
36
+ if (blocked !== undefined)
37
+ return blocked;
38
+ const port = parsePort(this.port);
39
+ if (port === undefined) {
40
+ this.context.writeErr("login: --port must be a whole number");
41
+ return 1;
42
+ }
43
+ if (!(await webShellInstalled(this.context)))
44
+ return 1;
45
+ const kernel = this.kernelPath();
46
+ return (await runRemote({ verb: "login", kernel, name: this.name, browser: this.browser }, this.context, {
47
+ prepare: async () => {
48
+ const door = await ensureServing(realServeDeps, { kernel, port }, serveOutput(this.context));
49
+ this.context.stderr.write(`web: ${door.url}\n`);
50
+ },
51
+ })).code;
52
+ }
53
+ }
54
+ export class LogoutCommand extends KernelCommand {
55
+ static paths = [["logout"]];
56
+ static usage = Command.Usage({
57
+ category: "Remote",
58
+ description: "drop this machine's remote access login",
59
+ });
60
+ async execute() {
61
+ const blocked = this.rejectUnsupportedAgentFlags("inhuman logout");
62
+ if (blocked !== undefined)
63
+ return blocked;
64
+ return (await runRemote({ verb: "logout", kernel: this.kernelPath() }, this.context)).code;
65
+ }
66
+ }
67
+ export class RemoteCommand extends KernelCommand {
68
+ static paths = [["remote"]];
69
+ static usage = Command.Usage({
70
+ category: "Remote",
71
+ description: "remote access",
72
+ });
73
+ async execute() {
74
+ const blocked = this.rejectUnsupportedAgentFlags("inhuman remote");
75
+ if (blocked !== undefined)
76
+ return blocked;
77
+ this.context.stderr.write("Specify a remote command: status\n");
78
+ return 2;
79
+ }
80
+ }
81
+ export class RemoteStatusCommand extends KernelCommand {
82
+ static paths = [["remote", "status"]];
83
+ static usage = Command.Usage({
84
+ category: "Remote",
85
+ description: "show remote access state",
86
+ details: ENV_HELP,
87
+ });
88
+ json = Option.Boolean("--json", false, { description: "print JSON" });
89
+ async execute() {
90
+ const blocked = this.rejectUnsupportedAgentFlags("inhuman remote status");
91
+ if (blocked !== undefined)
92
+ return blocked;
93
+ return (await runRemote({ verb: "status", kernel: this.kernelPath(), json: this.json }, this.context)).code;
94
+ }
95
+ }
96
+ export async function runRemote(args, streams, deps = {}) {
97
+ const owned = deps.rpc === undefined;
98
+ try {
99
+ if (args.verb === "login")
100
+ await deps.prepare?.();
101
+ const rpc = deps.rpc ?? (await openKernelRpc(args.kernel));
102
+ try {
103
+ switch (args.verb) {
104
+ case "login":
105
+ return await runLogin(rpc, streams, args, deps);
106
+ case "logout":
107
+ return await runLogout(rpc, streams);
108
+ case "status":
109
+ return await runStatus(rpc, streams, args.json === true);
110
+ }
111
+ // Unreachable: the verbs above are exhaustive.
112
+ return { code: 2 };
113
+ }
114
+ finally {
115
+ if (owned)
116
+ await rpc[Symbol.asyncDispose]();
117
+ }
118
+ }
119
+ catch (error) {
120
+ streams.writeErr(error);
121
+ return { code: 1 };
122
+ }
123
+ }
124
+ async function runLogin(rpc, streams, args, deps) {
125
+ const open = deps.openBrowser ?? openExternalUrl;
126
+ let result = await rpc.request("remote/login", args.name === undefined ? {} : { name: args.name });
127
+ while (isUiForm(result)) {
128
+ const url = result.body.match(/https?:\/\/[^\s"'<>\\]+/i)?.[0];
129
+ if (url === undefined)
130
+ throw new Error("remote/login: the daemon parked a form with no address");
131
+ const code = userCode(url);
132
+ streams.stderr.write(`Approve this machine for remote access:\n ${url}\n`);
133
+ if (code !== undefined)
134
+ streams.stderr.write(`Check that the page shows the code ${code}.\n`);
135
+ streams.stderr.write("Waiting for approval...\n");
136
+ if (args.browser !== false)
137
+ open(url);
138
+ result = await rpc.request("ui/resolve", { pending: result.pending, kind: "opened", url });
139
+ }
140
+ const reply = result;
141
+ if (reply.ok !== true) {
142
+ streams.writeErr("login cancelled");
143
+ return { code: 1 };
144
+ }
145
+ const who = reply.email === "" ? "signed in" : `signed in as ${reply.email}`;
146
+ streams.stdout.write(`${who}; machine ${reply.machineId}\n`);
147
+ return { code: 0 };
148
+ }
149
+ function userCode(url) {
150
+ try {
151
+ return new URL(url).searchParams.get("user_code") ?? undefined;
152
+ }
153
+ catch {
154
+ return undefined;
155
+ }
156
+ }
157
+ async function runLogout(rpc, streams) {
158
+ const reply = (await rpc.request("remote/logout", {}));
159
+ streams.stdout.write(reply.wasLoggedIn === true ? "signed out of remote access\n" : "was not signed in\n");
160
+ return { code: 0 };
161
+ }
162
+ async function runStatus(rpc, streams, json) {
163
+ const status = (await rpc.request("remote/status", {}));
164
+ if (json) {
165
+ streams.stdout.write(`${JSON.stringify(status)}\n`);
166
+ return { code: 0 };
167
+ }
168
+ const rows = [
169
+ [
170
+ "remote access",
171
+ status.loggedIn ? `signed in${status.email === undefined ? "" : ` as ${status.email}`}` : "signed out",
172
+ ],
173
+ ["machine", `${status.machineName} (${status.machineId})`],
174
+ ["relay", status.relayUrl],
175
+ ["connection", status.connected ? "connected" : status.loggedIn ? "not connected (retrying)" : "off"],
176
+ ...(status.lastError === undefined ? [] : [["last error", status.lastError]]),
177
+ ];
178
+ const width = Math.max(...rows.map(([label]) => label.length));
179
+ streams.stdout.write(`${rows.map(([label, value]) => `${label.padEnd(width)} ${value}`).join("\n")}\n`);
180
+ if (!status.loggedIn)
181
+ streams.stdout.write("run `inhuman login` to sign in\n");
182
+ return { code: 0 };
183
+ }
184
+ //# sourceMappingURL=remote-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-commands.js","sourceRoot":"","sources":["../../src/cli/remote-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Glance `scope !== ""` and `oneShot` are not conversation resume targets —
3
+ * listing them attaches workers.
4
+ */
5
+ export type ResumeOverview = {
6
+ readonly title?: string;
7
+ readonly lastMessageAt?: number;
8
+ readonly recipeScope?: string;
9
+ readonly oneShot?: boolean;
10
+ };
11
+ export type ResumeCompletion = {
12
+ readonly id: string;
13
+ readonly title: string;
14
+ readonly lastMessageAt: number;
15
+ readonly occupied: boolean;
16
+ };
17
+ export declare function listResumeCompletions(args: {
18
+ readonly sessions: Record<string, ResumeOverview | undefined>;
19
+ readonly occupied: ReadonlySet<string>;
20
+ readonly prefix?: string;
21
+ }): ResumeCompletion[];
22
+ /** `id<TAB>title · used|orphaned`. Description has no tab/colon (zsh `_describe`). */
23
+ export declare function formatResumeCompletion(row: ResumeCompletion): string;
24
+ //# sourceMappingURL=resume-complete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-complete.d.ts","sourceRoot":"","sources":["../../src/cli/resume-complete.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,CAAC,CAAC;IAC9D,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,gBAAgB,EAAE,CAmBrB;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAIpE"}
@@ -0,0 +1,35 @@
1
+ export function listResumeCompletions(args) {
2
+ const needle = (args.prefix ?? "").trim().toLowerCase();
3
+ const rows = [];
4
+ for (const [id, glance] of Object.entries(args.sessions)) {
5
+ if (glance == null || id.trim() === "")
6
+ continue;
7
+ if ((glance.recipeScope ?? "") !== "" || glance.oneShot === true)
8
+ continue;
9
+ const title = glance.title?.trim() ?? "";
10
+ if (needle !== "" && !id.toLowerCase().includes(needle) && !title.toLowerCase().includes(needle)) {
11
+ continue;
12
+ }
13
+ rows.push({
14
+ id,
15
+ title,
16
+ lastMessageAt: glance.lastMessageAt ?? 0,
17
+ occupied: args.occupied.has(id),
18
+ });
19
+ }
20
+ rows.sort((a, b) => b.lastMessageAt - a.lastMessageAt || a.id.localeCompare(b.id));
21
+ return rows;
22
+ }
23
+ /** `id<TAB>title · used|orphaned`. Description has no tab/colon (zsh `_describe`). */
24
+ export function formatResumeCompletion(row) {
25
+ const label = sanitize(row.title === "" ? row.id : row.title);
26
+ const scent = row.occupied ? "used" : "orphaned";
27
+ return `${row.id}\t${label} · ${scent}`;
28
+ }
29
+ function sanitize(text) {
30
+ return text
31
+ .replaceAll(/[\t\n\r]/g, " ")
32
+ .replaceAll(":", " ")
33
+ .trim();
34
+ }
35
+ //# sourceMappingURL=resume-complete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-complete.js","sourceRoot":"","sources":["../../src/cli/resume-complete.ts"],"names":[],"mappings":"AAkBA,MAAM,UAAU,qBAAqB,CAAC,IAIrC;IACC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxD,MAAM,IAAI,GAAuB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,IAAI,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,SAAS;QACjD,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI;YAAE,SAAS;QAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACzC,IAAI,MAAM,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACjG,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC;YACR,EAAE;YACF,KAAK;YACL,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,CAAC;YACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;SAChC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,sBAAsB,CAAC,GAAqB;IAC1D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;IACjD,OAAO,GAAG,GAAG,CAAC,EAAE,KAAK,KAAK,MAAM,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI;SACR,UAAU,CAAC,WAAW,EAAE,GAAG,CAAC;SAC5B,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The TUI and the web app are dependencies loaded on demand. A command loads its shell when it runs,
3
+ * so `inhuman daemon stop` and `inhuman mcp list` never pay for either. A shell that is not installed
4
+ * becomes an install hint; any other failure to load, a dependency of an installed shell included,
5
+ * keeps its stack: that is a broken install, not a missing shell.
6
+ */
7
+ import type { ShellContext } from "./context.js";
8
+ export type ShellPackage = {
9
+ /** What the user calls it in the hint: "TUI shell". */
10
+ readonly label: string;
11
+ /** The module handed to `import()`, subpath included. */
12
+ readonly specifier: string;
13
+ };
14
+ /**
15
+ * Node names the package, not the subpath, when it finds none: importing `@scope/web/server` fails with
16
+ * "Cannot find package '@scope/web' imported from ...". A message that names any other module, such as a
17
+ * file inside an installed shell or a package the shell itself needs, is not a missing shell.
18
+ */
19
+ export declare function isShellMissing(error: unknown, specifier: string): boolean;
20
+ /** The loaded shell, or `undefined` after one stderr line when the shell is not installed. */
21
+ export declare function importShell<T>(context: Pick<ShellContext, "writeErr">, shell: ShellPackage, load: () => Promise<T>): Promise<T | undefined>;
22
+ //# sourceMappingURL=shell-import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-import.d.ts","sourceRoot":"","sources":["../../src/cli/shell-import.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAQF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAMzE;AAED,8FAA8F;AAC9F,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EACvC,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAQxB"}
@@ -0,0 +1,32 @@
1
+ /** `@scope/name/sub` is `@scope/name`; `name/sub` is `name`. */
2
+ function packageNameOf(specifier) {
3
+ const parts = specifier.split("/");
4
+ return parts.slice(0, specifier.startsWith("@") ? 2 : 1).join("/");
5
+ }
6
+ /**
7
+ * Node names the package, not the subpath, when it finds none: importing `@scope/web/server` fails with
8
+ * "Cannot find package '@scope/web' imported from ...". A message that names any other module, such as a
9
+ * file inside an installed shell or a package the shell itself needs, is not a missing shell.
10
+ */
11
+ export function isShellMissing(error, specifier) {
12
+ if (!(error instanceof Error))
13
+ return false;
14
+ const { code } = error;
15
+ if (code !== "ERR_MODULE_NOT_FOUND" && code !== "MODULE_NOT_FOUND")
16
+ return false;
17
+ const named = /^Cannot find (?:package|module) '([^']+)'/.exec(error.message)?.[1];
18
+ return named === specifier || named === packageNameOf(specifier);
19
+ }
20
+ /** The loaded shell, or `undefined` after one stderr line when the shell is not installed. */
21
+ export async function importShell(context, shell, load) {
22
+ try {
23
+ return await load();
24
+ }
25
+ catch (error) {
26
+ if (!isShellMissing(error, shell.specifier))
27
+ throw error;
28
+ context.writeErr(`inhuman: the ${shell.label} is not installed — add ${packageNameOf(shell.specifier)}`);
29
+ return undefined;
30
+ }
31
+ }
32
+ //# sourceMappingURL=shell-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-import.js","sourceRoot":"","sources":["../../src/cli/shell-import.ts"],"names":[],"mappings":"AAeA,gEAAgE;AAChE,SAAS,aAAa,CAAC,SAAiB;IACtC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,SAAiB;IAC9D,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,EAAE,IAAI,EAAE,GAAG,KAA8B,CAAC;IAChD,IAAI,IAAI,KAAK,sBAAsB,IAAI,IAAI,KAAK,kBAAkB;QAAE,OAAO,KAAK,CAAC;IACjF,MAAM,KAAK,GAAG,2CAA2C,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACnF,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,aAAa,CAAC,SAAS,CAAC,CAAC;AACnE,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAuC,EACvC,KAAmB,EACnB,IAAsB;IAEtB,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;YAAE,MAAM,KAAK,CAAC;QACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,KAAK,CAAC,KAAK,2BAA2B,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACzG,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { KernelCommand } from "./context.js";
2
+ export declare class TuiCommand extends KernelCommand {
3
+ static paths: never[][];
4
+ static usage: import("clipanion").Usage;
5
+ session: string | undefined;
6
+ resume: string | undefined;
7
+ continueLast: boolean;
8
+ restartDaemon: boolean;
9
+ execute(): Promise<number>;
10
+ }
11
+ //# sourceMappingURL=tui-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-command.d.ts","sourceRoot":"","sources":["../../src/cli/tui-command.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,qBAAa,UAAW,SAAQ,aAAa;IAC3C,MAAM,CAAC,KAAK,YAAqB;IACjC,MAAM,CAAC,KAAK,4BAET;IAEH,OAAO,qBAA6D;IACpE,MAAM,qBAA2E;IACjF,YAAY,UAET;IACH,aAAa,UAEV;IAEG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAqBjC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `--session` / `--resume` / `--continue` and `--restart-daemon` live only here —
3
+ * daemon/mcp must not see them.
4
+ */
5
+ import { ensure } from "@inhuman.tools/harness";
6
+ import { Command, Option } from "clipanion";
7
+ import { KernelCommand } from "./context.js";
8
+ import { importShell } from "./shell-import.js";
9
+ export class TuiCommand extends KernelCommand {
10
+ static paths = [Command.Default];
11
+ static usage = Command.Usage({
12
+ description: "attach the TUI to the daemon",
13
+ });
14
+ session = Option.String("--session", { description: "session id" });
15
+ resume = Option.String("--resume", { description: "session id (tab-complete)" });
16
+ continueLast = Option.Boolean("--continue,-c", false, {
17
+ description: "restore this tab's last session",
18
+ });
19
+ restartDaemon = Option.Boolean("--restart-daemon", false, {
20
+ description: "stop a live daemon before attach",
21
+ });
22
+ async execute() {
23
+ if (this.continueLast && (this.session != null || this.resume != null)) {
24
+ this.context.writeErr("cannot combine --continue with --resume or --session");
25
+ return 2;
26
+ }
27
+ const tui = await importShell(this.context, { label: "TUI shell", specifier: "@inhuman.tools/harness-tui" }, () => import("@inhuman.tools/harness-tui"));
28
+ if (tui === undefined)
29
+ return 1;
30
+ return tui.attachTui({
31
+ kernel: this.kernelPath(),
32
+ session: this.session ?? this.resume,
33
+ continueLast: this.continueLast,
34
+ restartDaemon: this.restartDaemon,
35
+ agent: this.cliAgentFlags(),
36
+ streams: this.context,
37
+ ensure,
38
+ });
39
+ }
40
+ }
41
+ //# sourceMappingURL=tui-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-command.js","sourceRoot":"","sources":["../../src/cli/tui-command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,OAAO,UAAW,SAAQ,aAAa;IAC3C,MAAM,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,WAAW,EAAE,8BAA8B;KAC5C,CAAC,CAAC;IAEH,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;IACpE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC,CAAC;IACjF,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,EAAE;QACpD,WAAW,EAAE,iCAAiC;KAC/C,CAAC,CAAC;IACH,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,KAAK,EAAE;QACxD,WAAW,EAAE,kCAAkC;KAChD,CAAC,CAAC;IAEH,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,sDAAsD,CAAC,CAAC;YAC9E,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,WAAW,CAC3B,IAAI,CAAC,OAAO,EACZ,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,4BAA4B,EAAE,EAC/D,GAAG,EAAE,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAC3C,CAAC;QACF,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC;QAChC,OAAO,GAAG,CAAC,SAAS,CAAC;YACnB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM;YACpC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM;SACP,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { KernelCommand, type ShellContext } from "./context.js";
2
+ import { type DoorRecord } from "./web-door.js";
3
+ export type ServeDeps = {
4
+ readonly daemonRunning: (kernel: string) => Promise<boolean>;
5
+ readonly ensure: (kernel: string) => Promise<void>;
6
+ readonly findDoor: (kernel: string) => Promise<DoorRecord | undefined>;
7
+ readonly startDoor: (kernel: string, port: number) => Promise<DoorRecord>;
8
+ readonly openBrowser: (url: string) => void;
9
+ };
10
+ export type ServeOptions = {
11
+ readonly kernel: string;
12
+ readonly port: number;
13
+ };
14
+ export type WebOptions = ServeOptions & {
15
+ readonly browser: boolean;
16
+ };
17
+ export type ServeOutput = {
18
+ readonly out: (line: string) => void;
19
+ readonly err: (line: string) => void;
20
+ };
21
+ /**
22
+ * Daemon up and web door up, both left running in the background. Progress goes to `err`; the caller
23
+ * decides what to print and whether to open a browser. Shared by `start`, `web` and `login`.
24
+ */
25
+ export declare function ensureServing(deps: ServeDeps, options: ServeOptions, output: ServeOutput): Promise<DoorRecord>;
26
+ /** `inhuman start`: serve in the background, print the URL, never open a browser. */
27
+ export declare function runStart(deps: ServeDeps, options: ServeOptions, output: ServeOutput): Promise<number>;
28
+ /** `inhuman web`: serve in the background, print the URL, open the browser unless told not to. */
29
+ export declare function runWeb(deps: ServeDeps, options: WebOptions, output: ServeOutput): Promise<number>;
30
+ export declare const realServeDeps: ServeDeps;
31
+ export declare function serveOutput(context: ShellContext): ServeOutput;
32
+ export declare function parsePort(value: string): number | undefined;
33
+ /** Fails with the install hint before the daemon starts, not after. */
34
+ export declare function webShellInstalled(context: ShellContext): Promise<boolean>;
35
+ declare abstract class ServeCommand extends KernelCommand {
36
+ abstract readonly verb: string;
37
+ port: string;
38
+ protected serve(run: (kernel: string, port: number) => Promise<number>): Promise<number>;
39
+ }
40
+ export declare class StartCommand extends ServeCommand {
41
+ static paths: string[][];
42
+ static usage: import("clipanion").Usage;
43
+ readonly verb = "start";
44
+ execute(): Promise<number>;
45
+ }
46
+ export declare class WebCommand extends ServeCommand {
47
+ static paths: string[][];
48
+ static usage: import("clipanion").Usage;
49
+ readonly verb = "web";
50
+ noBrowser: boolean;
51
+ execute(): Promise<number>;
52
+ }
53
+ export {};
54
+ //# sourceMappingURL=web-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-commands.d.ts","sourceRoot":"","sources":["../../src/cli/web-commands.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAErE,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACvE,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1E,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAUpH;AAED,qFAAqF;AACrF,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAI3G;AAED,kGAAkG;AAClG,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAKvG;AAED,eAAO,MAAM,aAAa,EAAE,SAM3B,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAK9D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG3D;AAED,uEAAuE;AACvE,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/E;AAED,uBAAe,YAAa,SAAQ,aAAa;IAC/C,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,IAAI,SAA+G;cAEnG,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAgB/F;AAED,qBAAa,YAAa,SAAQ,YAAY;IAC5C,MAAM,CAAC,KAAK,aAAe;IAC3B,MAAM,CAAC,KAAK,4BAMT;IACH,QAAQ,CAAC,IAAI,WAAW;IAExB,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAG3B;AAED,qBAAa,UAAW,SAAQ,YAAY;IAC1C,MAAM,CAAC,KAAK,aAAa;IACzB,MAAM,CAAC,KAAK,4BAGT;IACH,QAAQ,CAAC,IAAI,SAAS;IAEtB,SAAS,UAAqG;IAE9G,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAK3B"}
@@ -0,0 +1,106 @@
1
+ import { daemonRunning, ensure } from "@inhuman.tools/harness";
2
+ import { Command, Option } from "clipanion";
3
+ import { openBrowser } from "./browser.js";
4
+ import { KernelCommand } from "./context.js";
5
+ import { importShell } from "./shell-import.js";
6
+ import { liveDoor, startDoor } from "./web-door.js";
7
+ /**
8
+ * Daemon up and web door up, both left running in the background. Progress goes to `err`; the caller
9
+ * decides what to print and whether to open a browser. Shared by `start`, `web` and `login`.
10
+ */
11
+ export async function ensureServing(deps, options, output) {
12
+ const wasRunning = await deps.daemonRunning(options.kernel);
13
+ await deps.ensure(options.kernel);
14
+ output.err(wasRunning ? "daemon: already running" : "daemon: started");
15
+ const live = await deps.findDoor(options.kernel);
16
+ if (live !== undefined) {
17
+ output.err("web: reusing running door");
18
+ return live;
19
+ }
20
+ return deps.startDoor(options.kernel, options.port);
21
+ }
22
+ /** `inhuman start`: serve in the background, print the URL, never open a browser. */
23
+ export async function runStart(deps, options, output) {
24
+ const door = await ensureServing(deps, options, output);
25
+ output.out(door.url);
26
+ return 0;
27
+ }
28
+ /** `inhuman web`: serve in the background, print the URL, open the browser unless told not to. */
29
+ export async function runWeb(deps, options, output) {
30
+ const door = await ensureServing(deps, options, output);
31
+ output.out(door.url);
32
+ if (options.browser)
33
+ deps.openBrowser(door.url);
34
+ return 0;
35
+ }
36
+ export const realServeDeps = {
37
+ daemonRunning: (kernel) => daemonRunning(kernel),
38
+ ensure: (kernel) => ensure(kernel),
39
+ findDoor: (kernel) => liveDoor(kernel),
40
+ startDoor,
41
+ openBrowser,
42
+ };
43
+ export function serveOutput(context) {
44
+ return {
45
+ out: (line) => context.stdout.write(`${line}\n`),
46
+ err: (line) => context.stderr.write(`${line}\n`),
47
+ };
48
+ }
49
+ export function parsePort(value) {
50
+ const port = Number(value);
51
+ return Number.isInteger(port) && port >= 0 ? port : undefined;
52
+ }
53
+ /** Fails with the install hint before the daemon starts, not after. */
54
+ export async function webShellInstalled(context) {
55
+ const web = await importShell(context, { label: "web shell", specifier: "@inhuman.tools/harness-web-app/server" }, () => import("@inhuman.tools/harness-web-app/server"));
56
+ return web !== undefined;
57
+ }
58
+ class ServeCommand extends KernelCommand {
59
+ port = Option.String("--port", "8787", { description: "preferred loopback port; a free one is picked when busy" });
60
+ async serve(run) {
61
+ const blocked = this.rejectUnsupportedAgentFlags(`inhuman ${this.verb}`);
62
+ if (blocked !== undefined)
63
+ return blocked;
64
+ const port = parsePort(this.port);
65
+ if (port === undefined) {
66
+ this.context.writeErr(`${this.verb}: --port must be a whole number`);
67
+ return 1;
68
+ }
69
+ if (!(await webShellInstalled(this.context)))
70
+ return 1;
71
+ try {
72
+ return await run(this.kernelPath(), port);
73
+ }
74
+ catch (error) {
75
+ this.context.writeErr(error);
76
+ return 1;
77
+ }
78
+ }
79
+ }
80
+ export class StartCommand extends ServeCommand {
81
+ static paths = [["start"]];
82
+ static usage = Command.Usage({
83
+ category: "Client",
84
+ description: "start the daemon and its web server in the background, print the URL, and return",
85
+ details: `
86
+ Leaves the daemon and a loopback web server running. Does not open a browser; use \`inhuman web\` for that.
87
+ `,
88
+ });
89
+ verb = "start";
90
+ execute() {
91
+ return this.serve((kernel, port) => runStart(realServeDeps, { kernel, port }, serveOutput(this.context)));
92
+ }
93
+ }
94
+ export class WebCommand extends ServeCommand {
95
+ static paths = [["web"]];
96
+ static usage = Command.Usage({
97
+ category: "Client",
98
+ description: "start the daemon and web server if needed, then open the web client in the browser",
99
+ });
100
+ verb = "web";
101
+ noBrowser = Option.Boolean("--no-browser", false, { description: "print the URL without opening a browser" });
102
+ execute() {
103
+ return this.serve((kernel, port) => runWeb(realServeDeps, { kernel, port, browser: !this.noBrowser }, serveOutput(this.context)));
104
+ }
105
+ }
106
+ //# sourceMappingURL=web-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-commands.js","sourceRoot":"","sources":["../../src/cli/web-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { KernelCommand } from "./context.js";
2
+ /**
3
+ * Internal: the detached process `inhuman start` and `inhuman web` start. Serves the built client until the daemon is gone.
4
+ * It has no `usage`, so help does not list it.
5
+ */
6
+ export declare class WebDoorCommand extends KernelCommand {
7
+ static paths: string[][];
8
+ port: string;
9
+ execute(): Promise<number>;
10
+ }
11
+ //# sourceMappingURL=web-door-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-door-command.d.ts","sourceRoot":"","sources":["../../src/cli/web-door-command.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C;;;GAGG;AACH,qBAAa,cAAe,SAAQ,aAAa;IAC/C,MAAM,CAAC,KAAK,aAAkB;IAE9B,IAAI,SAAmC;IAEjC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAmEjC"}