automify 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.
Files changed (47) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +401 -0
  4. package/SECURITY.md +17 -0
  5. package/examples/anthropic-provider.js +18 -0
  6. package/examples/browser-basic.js +30 -0
  7. package/examples/browser-with-safety.js +38 -0
  8. package/examples/claude-model-adapter.js +141 -0
  9. package/examples/cli-basic.js +20 -0
  10. package/examples/cli-docker.js +42 -0
  11. package/examples/custom-computer.js +18 -0
  12. package/examples/custom-model-adapter.js +48 -0
  13. package/examples/desktop-docker.js +37 -0
  14. package/examples/desktop-local.js +28 -0
  15. package/examples/evaluate-image.js +26 -0
  16. package/examples/files-and-shared-folder.js +42 -0
  17. package/package.json +74 -0
  18. package/scripts/generate-argument-reference.js +17 -0
  19. package/scripts/install-browser.js +12 -0
  20. package/scripts/install-desktop.js +281 -0
  21. package/src/index.d.ts +1049 -0
  22. package/src/index.js +83 -0
  23. package/src/lib/adapter-locks.js +93 -0
  24. package/src/lib/adapter-toolkit.js +239 -0
  25. package/src/lib/anthropic-model-adapter.js +451 -0
  26. package/src/lib/argument-reference.js +98 -0
  27. package/src/lib/automify.js +938 -0
  28. package/src/lib/browser-automify.js +89 -0
  29. package/src/lib/cli-automify.js +520 -0
  30. package/src/lib/computer-automify.js +103 -0
  31. package/src/lib/docker-cli-automify.js +517 -0
  32. package/src/lib/docker-desktop-computer.js +725 -0
  33. package/src/lib/errors.js +24 -0
  34. package/src/lib/file-data.js +140 -0
  35. package/src/lib/init.js +217 -0
  36. package/src/lib/local-desktop-computer.js +963 -0
  37. package/src/lib/model-adapter.js +32 -0
  38. package/src/lib/openai-responses-client.js +162 -0
  39. package/src/lib/output.js +57 -0
  40. package/src/lib/playwright-computer.js +363 -0
  41. package/src/lib/presets.js +141 -0
  42. package/src/lib/result.js +95 -0
  43. package/src/lib/runtime.js +471 -0
  44. package/src/lib/virtual-shared-folder.js +109 -0
  45. package/src/lib/zod-output.js +26 -0
  46. package/src/zod.d.ts +12 -0
  47. package/src/zod.js +5 -0
@@ -0,0 +1,109 @@
1
+ import { copyFile, mkdir, mkdtemp, rm, stat } from "node:fs/promises";
2
+ import { basename, dirname, join, relative, resolve } from "node:path";
3
+ import { tmpdir } from "node:os";
4
+
5
+ import { AutomifyError } from "./errors.js";
6
+
7
+ const DEFAULT_CONTAINER_PATH = "/workspace";
8
+
9
+ export async function prepareVirtualSharedFolder(options = {}, defaults = {}) {
10
+ const sharedFiles = options.sharedFiles ?? options.files;
11
+ const requested = options.sharedFolder ?? options.shared ?? (sharedFiles?.length ? true : null);
12
+ if (!requested) return null;
13
+
14
+ const config = normalizeSharedFolder(requested);
15
+ const containerPath = normalizeContainerPath(config.containerPath ?? defaults.containerPath ?? DEFAULT_CONTAINER_PATH);
16
+ const hostPath = config.hostPath
17
+ ? resolve(config.hostPath)
18
+ : await mkdtemp(join(tmpdir(), defaults.prefix ?? "automify-shared-"));
19
+ const cleanup = !config.hostPath && config.cleanup !== false && options.keepContainer !== true;
20
+
21
+ await mkdir(hostPath, { recursive: true });
22
+
23
+ const copiedFiles = [];
24
+ const files = [
25
+ ...(Array.isArray(config.files) ? config.files : []),
26
+ ...(Array.isArray(sharedFiles) ? sharedFiles : [])
27
+ ];
28
+ for (const file of files) {
29
+ copiedFiles.push(await copySharedFile(file, hostPath, containerPath));
30
+ }
31
+
32
+ const readOnly = config.readOnly === true;
33
+ return {
34
+ hostPath,
35
+ containerPath,
36
+ readOnly,
37
+ volume: `${hostPath}:${containerPath}${readOnly ? ":ro" : ":rw"}`,
38
+ files: copiedFiles,
39
+ data: {
40
+ hostPath,
41
+ containerPath,
42
+ files: copiedFiles.map(({ sourcePath, ...file }) => file)
43
+ },
44
+ async close() {
45
+ if (cleanup) {
46
+ await rm(hostPath, { recursive: true, force: true });
47
+ }
48
+ }
49
+ };
50
+ }
51
+
52
+ function normalizeSharedFolder(value) {
53
+ if (value === true) return {};
54
+ if (typeof value === "string") return { hostPath: value };
55
+ if (value && typeof value === "object") {
56
+ return {
57
+ ...value,
58
+ hostPath: value.hostPath ?? value.path
59
+ };
60
+ }
61
+ throw new AutomifyError("sharedFolder must be true, a host path, or a shared folder options object.");
62
+ }
63
+
64
+ async function copySharedFile(file, hostPath, containerPath) {
65
+ const descriptor = normalizeFile(file);
66
+ const sourcePath = resolve(descriptor.path);
67
+ const info = await stat(sourcePath);
68
+ if (!info.isFile()) {
69
+ throw new AutomifyError(`sharedFolder files must be regular files: ${sourcePath}`);
70
+ }
71
+
72
+ const targetPath = normalizeRelativeTarget(descriptor.targetPath ?? descriptor.name ?? basename(sourcePath));
73
+ const destinationPath = join(hostPath, targetPath);
74
+ await mkdir(dirname(destinationPath), { recursive: true });
75
+ await copyFile(sourcePath, destinationPath);
76
+
77
+ return {
78
+ name: basename(targetPath),
79
+ relativePath: targetPath,
80
+ hostPath: destinationPath,
81
+ containerPath: joinContainerPath(containerPath, targetPath),
82
+ sourcePath,
83
+ size: info.size
84
+ };
85
+ }
86
+
87
+ function normalizeFile(file) {
88
+ if (typeof file === "string") return { path: file };
89
+ if (file && typeof file === "object" && typeof file.path === "string") return file;
90
+ throw new AutomifyError("sharedFolder files must be paths or objects with a path.");
91
+ }
92
+
93
+ function normalizeRelativeTarget(value) {
94
+ const raw = String(value || "").replaceAll("\\", "/");
95
+ const normalized = relative("/", `/${raw}`);
96
+ if (!normalized || normalized.startsWith("..")) {
97
+ throw new AutomifyError(`Invalid shared file target path: ${value}`);
98
+ }
99
+ return normalized;
100
+ }
101
+
102
+ function normalizeContainerPath(value) {
103
+ const path = String(value || DEFAULT_CONTAINER_PATH).trim();
104
+ return path.startsWith("/") ? path : `/${path}`;
105
+ }
106
+
107
+ function joinContainerPath(base, target) {
108
+ return `${base.replace(/\/+$/, "")}/${target.replace(/^\/+/, "")}`;
109
+ }
@@ -0,0 +1,26 @@
1
+ import { jsonOutput } from "./output.js";
2
+ import { AutomifyError } from "./errors.js";
3
+
4
+ export function createZodOutput(zod) {
5
+ if (!zod || typeof zod.toJSONSchema !== "function") {
6
+ throw new AutomifyError("Zod output support requires Zod 4 with z.toJSONSchema().");
7
+ }
8
+
9
+ return function zodOutput(name, schema, options = {}) {
10
+ if (!schema || typeof schema !== "object") {
11
+ throw new AutomifyError("zodOutput requires a Zod schema.");
12
+ }
13
+
14
+ if (typeof schema.parse !== "function") {
15
+ throw new AutomifyError("zodOutput schema must expose a parse() function.");
16
+ }
17
+
18
+ return {
19
+ ...jsonOutput(name, zod.toJSONSchema(schema, options.zodToJsonSchema)),
20
+ description: options.description,
21
+ strict: options.strict ?? true,
22
+ parse: options.parse,
23
+ parseResult: options.parse === false ? undefined : (value) => schema.parse(value)
24
+ };
25
+ };
26
+ }
package/src/zod.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { JsonOutputOptions, OutputFormat } from "./index.js";
2
+ import type { ZodType } from "zod";
3
+
4
+ export interface ZodOutputOptions extends JsonOutputOptions {
5
+ zodToJsonSchema?: Record<string, unknown>;
6
+ }
7
+
8
+ export function zodOutput<T>(
9
+ name: string,
10
+ schema: ZodType<T>,
11
+ options?: ZodOutputOptions
12
+ ): OutputFormat & { readonly __output?: T };
package/src/zod.js ADDED
@@ -0,0 +1,5 @@
1
+ import * as z from "zod";
2
+
3
+ import { createZodOutput } from "./lib/zod-output.js";
4
+
5
+ export const zodOutput = createZodOutput(z);