humanish 0.141.0 → 0.143.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 (99) hide show
  1. package/ARCHITECTURE.md +1 -0
  2. package/CHANGELOG.md +21 -0
  3. package/README.md +3 -1
  4. package/dist/analysis/admission.d.ts +8 -0
  5. package/dist/analysis/admission.js +15 -4
  6. package/dist/analysis/automatic-config.d.ts +17 -3
  7. package/dist/analysis/automatic-config.js +56 -12
  8. package/dist/analysis/automatic.js +13 -7
  9. package/dist/analysis/execute.d.ts +6 -5
  10. package/dist/analysis/execute.js +27 -26
  11. package/dist/analysis/gemini-wire.d.ts +9 -0
  12. package/dist/analysis/gemini-wire.js +166 -0
  13. package/dist/analysis/image-tokens.d.ts +4 -2
  14. package/dist/analysis/image-tokens.js +24 -3
  15. package/dist/analysis/job.d.ts +1 -0
  16. package/dist/analysis/job.js +1 -0
  17. package/dist/analysis/models.d.ts +12 -0
  18. package/dist/analysis/models.js +47 -0
  19. package/dist/analysis/openai-wire.d.ts +6 -0
  20. package/dist/analysis/openai-wire.js +102 -0
  21. package/dist/analysis/provider.d.ts +19 -7
  22. package/dist/analysis/provider.js +21 -101
  23. package/dist/analysis/responses.d.ts +3 -0
  24. package/dist/analysis/responses.js +19 -0
  25. package/dist/analysis/service.js +11 -3
  26. package/dist/analysis/types.d.ts +12 -2
  27. package/dist/analysis/validation.d.ts +1 -0
  28. package/dist/analysis/validation.js +17 -15
  29. package/dist/cli/commands/analyze.js +11 -7
  30. package/dist/cli/commands/observe.js +26 -1
  31. package/dist/cli/commands/run-command.d.ts +1 -1
  32. package/dist/cli/commands/run-command.js +12 -0
  33. package/dist/cli/commands/study-remote.d.ts +13 -0
  34. package/dist/cli/commands/study-remote.js +125 -0
  35. package/dist/cli/commands/study-route-computer-use.js +26 -2
  36. package/dist/cli/commands/study-route-scripted.js +1 -0
  37. package/dist/cli/commands/study-route-shared-world.js +1 -0
  38. package/dist/cli/commands/study-route-terminal.js +1 -0
  39. package/dist/cli/commands/study-run.js +34 -0
  40. package/dist/cli/commands/watch.js +5 -0
  41. package/dist/cli/doctor.js +7 -2
  42. package/dist/cli/findings.d.ts +9 -1
  43. package/dist/cli/findings.js +62 -17
  44. package/dist/cli/io.d.ts +8 -0
  45. package/dist/cli/io.js +2 -1
  46. package/dist/keys/key-resolution.d.ts +10 -0
  47. package/dist/keys/key-resolution.js +33 -5
  48. package/dist/observer/listen.d.ts +7 -2
  49. package/dist/observer/listen.js +10 -4
  50. package/dist/observer/render.d.ts +2 -0
  51. package/dist/observer/render.js +1 -1
  52. package/dist/observer-app.html +1 -1
  53. package/dist/remote/launch.d.ts +56 -0
  54. package/dist/remote/launch.js +365 -0
  55. package/dist/remote/observer-proxy.d.ts +11 -0
  56. package/dist/remote/observer-proxy.js +66 -0
  57. package/dist/remote/plan.d.ts +35 -0
  58. package/dist/remote/plan.js +114 -0
  59. package/dist/remote/reattach.d.ts +17 -0
  60. package/dist/remote/reattach.js +81 -0
  61. package/dist/remote/runner.d.ts +84 -0
  62. package/dist/remote/runner.js +241 -0
  63. package/dist/routes/computer-use/e2b-desktop/start.js +1 -1
  64. package/dist/routes/computer-use/types.d.ts +2 -0
  65. package/dist/routes/scripted/types.d.ts +2 -0
  66. package/dist/routes/shared-world/types.d.ts +2 -0
  67. package/dist/routes/terminal/types.d.ts +2 -0
  68. package/dist/run/costs.d.ts +2 -1
  69. package/dist/run/pricing.d.ts +13 -1
  70. package/dist/run/pricing.js +50 -4
  71. package/dist/run/results.d.ts +1 -1
  72. package/dist/run/run-cost.d.ts +2 -1
  73. package/dist/run/run-cost.js +6 -1
  74. package/dist/run/run.d.ts +13 -0
  75. package/dist/run/run.js +18 -7
  76. package/dist/run/sandbox-creates.d.ts +10 -3
  77. package/dist/run/sandbox-creates.js +48 -6
  78. package/dist/run-study.d.ts +5 -0
  79. package/dist/study/doctor.js +14 -1
  80. package/dist/study/requirements.d.ts +1 -1
  81. package/dist/study/requirements.js +8 -6
  82. package/dist/study/route-inputs.js +4 -0
  83. package/dist/study/run-study-events.d.ts +1 -1
  84. package/dist/study/run-study-events.js +9 -2
  85. package/dist/substrates/e2b/base-module.d.ts +3 -0
  86. package/dist/substrates/e2b/base-module.js +40 -0
  87. package/dist/substrates/e2b/desktop-browser.d.ts +1 -1
  88. package/dist/substrates/e2b/desktop-browser.js +24 -6
  89. package/dist/substrates/e2b/sdk.d.ts +24 -0
  90. package/dist/substrates/e2b/sdk.js +5 -1
  91. package/dist/substrates/e2b/shell-only.d.ts +5 -0
  92. package/dist/substrates/e2b/shell-only.js +27 -0
  93. package/dist/substrates/modal/sandbox.js +27 -28
  94. package/dist/substrates/modal/sdk.d.ts +7 -0
  95. package/dist/tui-app.js +46 -46
  96. package/docs/contracts/study-analysis.md +85 -4
  97. package/docs/product/automatic-analysis.md +42 -8
  98. package/package.json +2 -2
  99. package/skills/humanish/SKILL.md +18 -1
@@ -7,6 +7,7 @@
7
7
  // default gVisor runtime sets no_new_privs on every process, so the user's sudo, which the Node
8
8
  // bootstrap and product installs run, cannot work there.
9
9
  import { E2BDesktopStartupError, reportDesktopAllocation } from "../e2b/sdk.js";
10
+ import { shellOnlySurface } from "../e2b/shell-only.js";
10
11
  import { readBytes, readFile, runCommand, sandboxPath, wholeSeconds, writeFile, } from "./commands.js";
11
12
  import { MODAL_DESKTOP_DISPLAY, MODAL_STREAM_PORT, modalDesktopSurface, startModalDesktop, } from "./desktop.js";
12
13
  import { MODAL_SANDBOX_USER, modalDesktopImage, modalShellImage } from "./image.js";
@@ -70,9 +71,7 @@ export function modalSandboxModule(client, connection, profile) {
70
71
  ...(options.resolution === undefined ? {} : { resolution: options.resolution }),
71
72
  ...(options.dpi === undefined ? {} : { dpi: options.dpi }),
72
73
  });
73
- const tunnels = await sandbox.tunnels(30_000);
74
- const hosts = new Map(Object.entries(tunnels).map(([port, tunnel]) => [Number(port), new URL(tunnel.url).host]));
75
- return modalSandboxHandle(sandbox, profile, connection, hosts);
74
+ return modalSandboxHandle(sandbox, profile, connection, await tunnelHosts(sandbox));
76
75
  }
77
76
  catch (error) {
78
77
  const gone = await modalSandboxes(client, connection)
@@ -82,13 +81,33 @@ export function modalSandboxModule(client, connection, profile) {
82
81
  throw new E2BDesktopStartupError(error, gone);
83
82
  }
84
83
  }
84
+ async function connect(sandboxId, options) {
85
+ const ms = options?.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
86
+ let sandbox;
87
+ try {
88
+ sandbox = await within(client.sandboxes.fromId(sandboxId), ms, "a sandbox lookup");
89
+ if ((await within(sandbox.poll(), ms, "a sandbox poll")) !== null)
90
+ throw sandboxNotFound(sandboxId);
91
+ }
92
+ catch (error) {
93
+ throw isModalNotFoundError(error) ? sandboxNotFound(sandboxId) : error;
94
+ }
95
+ const hosts = profile.desktop === true ? await tunnelHosts(sandbox) : new Map();
96
+ return modalSandboxHandle(sandbox, profile, connection, hosts);
97
+ }
85
98
  return {
86
99
  Sandbox: {
87
100
  create: hidingTokens(connection, create),
101
+ connect: hidingTokens(connection, connect),
88
102
  ...modalSandboxes(client, connection),
89
103
  },
90
104
  };
91
105
  }
106
+ /** The host of each tunnel a desktop sandbox exposes, by port. */
107
+ async function tunnelHosts(sandbox) {
108
+ const tunnels = await sandbox.tunnels(30_000);
109
+ return new Map(Object.entries(tunnels).map(([port, tunnel]) => [Number(port), new URL(tunnel.url).host]));
110
+ }
92
111
  /** The humanish App in the connection's environment; only a create may make it. */
93
112
  function appLookup(client, connection, createIfMissing) {
94
113
  let app;
@@ -240,6 +259,10 @@ function modalSandboxHandle(sandbox, profile, connection, hosts) {
240
259
  const run = hidingTokens(connection, (command, options) => runCommand(sandbox, command, options));
241
260
  const shell = {
242
261
  sandboxId: sandbox.sandboxId,
262
+ portAccess: hidingTokens(connection, async (port) => {
263
+ const { url, token } = await sandbox.createConnectToken({ port });
264
+ return { url, headers: { Authorization: `Bearer ${token}` } };
265
+ }),
243
266
  // Modal reports no allocation for a sandbox; the create's request is what it bills.
244
267
  getInfo: () => Promise.resolve({ cpuCount: profile.cpu * 2, memoryMB: profile.memoryMiB }),
245
268
  commands: { run },
@@ -257,31 +280,7 @@ function modalSandboxHandle(sandbox, profile, connection, hosts) {
257
280
  ...shell,
258
281
  ...modalDesktopSurface(run, hidingTokens(connection, (path) => readBytes(sandbox, path)), hosts),
259
282
  };
260
- const desktopOnly = (what) => () => Promise.reject(new ModalUnsupportedError(what));
261
- return {
262
- ...shell,
263
- wait: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
264
- launch: desktopOnly("A desktop application launch"),
265
- screenshot: desktopOnly("A desktop screenshot"),
266
- leftClick: desktopOnly("Desktop input"),
267
- rightClick: desktopOnly("Desktop input"),
268
- middleClick: desktopOnly("Desktop input"),
269
- doubleClick: desktopOnly("Desktop input"),
270
- moveMouse: desktopOnly("Desktop input"),
271
- scroll: desktopOnly("Desktop input"),
272
- write: desktopOnly("Desktop input"),
273
- press: desktopOnly("Desktop input"),
274
- drag: desktopOnly("Desktop input"),
275
- stream: {
276
- getAuthKey: () => {
277
- throw new ModalUnsupportedError("A desktop stream");
278
- },
279
- getUrl: () => {
280
- throw new ModalUnsupportedError("A desktop stream");
281
- },
282
- start: desktopOnly("A desktop stream"),
283
- },
284
- };
283
+ return { ...shell, ...shellOnlySurface((what) => new ModalUnsupportedError(what)) };
285
284
  }
286
285
  /** The Modal account `env` names, for release by id and reclaim. Throws when it names none. */
287
286
  export async function modalAccount(env, load = loadModalModule) {
@@ -51,6 +51,13 @@ export interface ModalSandbox {
51
51
  tunnels(timeoutMs?: number): Promise<Record<number, {
52
52
  url: string;
53
53
  }>>;
54
+ /** A URL to `port` and a token Modal's proxy requires as `Authorization: Bearer <token>`. */
55
+ createConnectToken(params?: {
56
+ port?: number;
57
+ }): Promise<{
58
+ url: string;
59
+ token: string;
60
+ }>;
54
61
  }
55
62
  export interface ModalSandboxCreateParams {
56
63
  cpu?: number;