@kernel.chat/kbot 4.1.1 → 4.4.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 (36) hide show
  1. package/dist/adapters/agent-sdk/from-agent-sdk.d.ts +28 -0
  2. package/dist/adapters/agent-sdk/from-agent-sdk.js +107 -0
  3. package/dist/adapters/agent-sdk/index.d.ts +4 -0
  4. package/dist/adapters/agent-sdk/index.js +14 -0
  5. package/dist/adapters/agent-sdk/to-agent-sdk.d.ts +13 -0
  6. package/dist/adapters/agent-sdk/to-agent-sdk.js +73 -0
  7. package/dist/adapters/agent-sdk/types.d.ts +41 -0
  8. package/dist/adapters/agent-sdk/types.js +9 -0
  9. package/dist/adapters/peekaboo/commands.d.ts +42 -0
  10. package/dist/adapters/peekaboo/commands.js +209 -0
  11. package/dist/adapters/peekaboo/index.d.ts +4 -0
  12. package/dist/adapters/peekaboo/index.js +9 -0
  13. package/dist/adapters/peekaboo/runner.d.ts +25 -0
  14. package/dist/adapters/peekaboo/runner.js +75 -0
  15. package/dist/adapters/peekaboo/types.d.ts +69 -0
  16. package/dist/adapters/peekaboo/types.js +8 -0
  17. package/dist/cli.js +15 -1
  18. package/dist/permissions.d.ts +17 -0
  19. package/dist/permissions.js +48 -0
  20. package/dist/tool-pipeline.js +11 -0
  21. package/dist/tools/computer.js +64 -0
  22. package/dist/tools/peekaboo.d.ts +4 -0
  23. package/dist/tools/peekaboo.js +371 -0
  24. package/dist/tools/security-audit-local.d.ts +47 -0
  25. package/dist/tools/security-audit-local.js +363 -0
  26. package/dist/tools/stream-overlay.d.ts +9 -0
  27. package/dist/tools/stream-overlay.js +167 -134
  28. package/dist/tools/stream-renderer.js +10 -1
  29. package/dist/tools/swarm-2026-04.js +4 -0
  30. package/package.json +1 -1
  31. package/skills/ai-engineering/full-stack-mastery/SKILL.md +174 -0
  32. package/skills/native-automation/peekaboo-snapshot-act/SKILL.md +91 -0
  33. package/skills/security-audit/dependency-audit/SKILL.md +102 -0
  34. package/skills/security-audit/local-vulnerability-hunt/SKILL.md +127 -0
  35. package/skills/security-audit/secrets-leak-scan/SKILL.md +109 -0
  36. package/skills/security-audit/threat-model-quickdraw/SKILL.md +107 -0
@@ -0,0 +1,28 @@
1
+ import type { ToolDefinition } from '../../tools/index.js';
2
+ import type { AgentSdkExecutableTool, AgentSdkTool } from './types.js';
3
+ export interface FromAgentSdkOptions {
4
+ /** kbot tier to assign to the imported tool. Default 'free'. */
5
+ tier?: ToolDefinition['tier'];
6
+ /** Custom timeout (ms). */
7
+ timeout?: number;
8
+ /** Max result size (bytes). */
9
+ maxResultSize?: number;
10
+ /**
11
+ * Fallback executor when the source tool ships no handler. Useful when the
12
+ * caller routes execution elsewhere (e.g., back through the Anthropic SDK).
13
+ */
14
+ fallbackExecutor?: (toolName: string, args: Record<string, unknown>) => Promise<string> | string;
15
+ }
16
+ /**
17
+ * Convert a non-executable Agent SDK tool definition into a kbot ToolDefinition.
18
+ * Because the source has no handler, an executor must be supplied via opts.fallbackExecutor
19
+ * — otherwise the resulting tool will return a structured "no handler" error string when invoked.
20
+ */
21
+ export declare function fromAgentSdkTool(tool: AgentSdkTool, opts?: FromAgentSdkOptions): ToolDefinition;
22
+ /**
23
+ * Convert an executable Agent SDK tool (schema + handler) into a kbot ToolDefinition.
24
+ * Preferred over fromAgentSdkTool() when the caller has the implementation in process.
25
+ */
26
+ export declare function fromAgentSdkExecutableTool(tool: AgentSdkExecutableTool, opts?: Omit<FromAgentSdkOptions, 'fallbackExecutor'>): ToolDefinition;
27
+ export declare function fromAgentSdkTools(tools: AgentSdkTool[], opts?: FromAgentSdkOptions): ToolDefinition[];
28
+ //# sourceMappingURL=from-agent-sdk.d.ts.map
@@ -0,0 +1,107 @@
1
+ // Anthropic Agent SDK tool → kbot ToolDefinition
2
+ //
3
+ // Lets a kbot host import third-party Agent SDK tools (or hand-written
4
+ // schema/handler pairs) and register them in the kbot tool registry. Schema
5
+ // is downconverted from JSON Schema to kbot's flatter parameter shape.
6
+ //
7
+ // Inverse of to-agent-sdk.ts. Round-trip is lossy in general (JSON Schema is
8
+ // strictly richer than kbot's shape), but is stable for the param shapes
9
+ // that kbot itself uses.
10
+ const JSON_TO_KBOT = {
11
+ string: 'string',
12
+ number: 'number',
13
+ integer: 'integer',
14
+ boolean: 'boolean',
15
+ object: 'object',
16
+ array: 'array',
17
+ null: 'null',
18
+ };
19
+ function pickType(t) {
20
+ if (typeof t === 'string')
21
+ return JSON_TO_KBOT[t] ?? 'string';
22
+ if (Array.isArray(t)) {
23
+ // Pick the first non-null type to keep parity with kbot's single-type shape.
24
+ const first = t.find((x) => x !== 'null');
25
+ return first ? JSON_TO_KBOT[first] ?? 'string' : 'string';
26
+ }
27
+ return 'string';
28
+ }
29
+ function mapProperty(p, required) {
30
+ const out = {
31
+ type: pickType(p.type),
32
+ description: typeof p.description === 'string' ? p.description : '',
33
+ required,
34
+ };
35
+ if (p.default !== undefined)
36
+ out.default = p.default;
37
+ if (p.items !== undefined)
38
+ out.items = p.items;
39
+ if (p.properties)
40
+ out.properties = p.properties;
41
+ return out;
42
+ }
43
+ function buildParameters(schema) {
44
+ if (!schema || typeof schema !== 'object')
45
+ return {};
46
+ const required = new Set(schema.required ?? []);
47
+ const out = {};
48
+ for (const [name, prop] of Object.entries(schema.properties ?? {})) {
49
+ out[name] = mapProperty(prop, required.has(name));
50
+ }
51
+ return out;
52
+ }
53
+ /**
54
+ * Convert a non-executable Agent SDK tool definition into a kbot ToolDefinition.
55
+ * Because the source has no handler, an executor must be supplied via opts.fallbackExecutor
56
+ * — otherwise the resulting tool will return a structured "no handler" error string when invoked.
57
+ */
58
+ export function fromAgentSdkTool(tool, opts = {}) {
59
+ const fallback = opts.fallbackExecutor;
60
+ return {
61
+ name: tool.name,
62
+ description: tool.description,
63
+ parameters: buildParameters(tool.input_schema),
64
+ tier: opts.tier ?? 'free',
65
+ timeout: opts.timeout,
66
+ maxResultSize: opts.maxResultSize,
67
+ async execute(args) {
68
+ if (fallback) {
69
+ try {
70
+ const result = await fallback(tool.name, args);
71
+ return typeof result === 'string' ? result : JSON.stringify(result, null, 2);
72
+ }
73
+ catch (e) {
74
+ return `Error: ${e.message}`;
75
+ }
76
+ }
77
+ return `Error: tool "${tool.name}" was imported without a handler. Provide opts.fallbackExecutor when calling fromAgentSdkTool().`;
78
+ },
79
+ };
80
+ }
81
+ /**
82
+ * Convert an executable Agent SDK tool (schema + handler) into a kbot ToolDefinition.
83
+ * Preferred over fromAgentSdkTool() when the caller has the implementation in process.
84
+ */
85
+ export function fromAgentSdkExecutableTool(tool, opts = {}) {
86
+ return {
87
+ name: tool.name,
88
+ description: tool.description,
89
+ parameters: buildParameters(tool.input_schema),
90
+ tier: opts.tier ?? 'free',
91
+ timeout: opts.timeout,
92
+ maxResultSize: opts.maxResultSize,
93
+ async execute(args) {
94
+ try {
95
+ const result = await tool.handler(args);
96
+ return typeof result === 'string' ? result : JSON.stringify(result, null, 2);
97
+ }
98
+ catch (e) {
99
+ return `Error: ${e.message}`;
100
+ }
101
+ },
102
+ };
103
+ }
104
+ export function fromAgentSdkTools(tools, opts = {}) {
105
+ return tools.map((t) => fromAgentSdkTool(t, opts));
106
+ }
107
+ //# sourceMappingURL=from-agent-sdk.js.map
@@ -0,0 +1,4 @@
1
+ export type { AgentSdkTool, AgentSdkExecutableTool, AgentSdkInputSchema, JsonSchemaProperty, JsonSchemaType, } from './types.js';
2
+ export { toAgentSdkTool, toAgentSdkTools, type ToAgentSdkOptions, } from './to-agent-sdk.js';
3
+ export { fromAgentSdkTool, fromAgentSdkExecutableTool, fromAgentSdkTools, type FromAgentSdkOptions, } from './from-agent-sdk.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,14 @@
1
+ // Anthropic Agent SDK adapter — bidirectional schema translation between
2
+ // kbot's ToolDefinition surface and the Agent SDK / Messages API tool surface.
3
+ //
4
+ // kbot stays provider-agnostic — this adapter takes no runtime dependency
5
+ // on @anthropic-ai/sdk. It only translates schemas and (for the from-side)
6
+ // wraps optional executors. Round-trip kbot → Agent SDK → kbot is stable
7
+ // for the parameter shapes kbot itself uses.
8
+ //
9
+ // Background: with the Anthropic Agent SDK opening to external developers
10
+ // in May 2026, kbot tools can now be advertised to that ecosystem and
11
+ // vice-versa — without coupling the registry to one provider's runtime.
12
+ export { toAgentSdkTool, toAgentSdkTools, } from './to-agent-sdk.js';
13
+ export { fromAgentSdkTool, fromAgentSdkExecutableTool, fromAgentSdkTools, } from './from-agent-sdk.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,13 @@
1
+ import type { ToolDefinition } from '../../tools/index.js';
2
+ import type { AgentSdkTool } from './types.js';
3
+ export interface ToAgentSdkOptions {
4
+ /** If true (default), kbot tool names are passed through unchanged. */
5
+ preserveName?: boolean;
6
+ /** Optional rename hook. Wins over preserveName. */
7
+ renameTool?: (name: string) => string;
8
+ /** If true, pass `additionalProperties: false` on the input schema. Default true. */
9
+ strict?: boolean;
10
+ }
11
+ export declare function toAgentSdkTool(tool: ToolDefinition, opts?: ToAgentSdkOptions): AgentSdkTool;
12
+ export declare function toAgentSdkTools(tools: ToolDefinition[], opts?: ToAgentSdkOptions): AgentSdkTool[];
13
+ //# sourceMappingURL=to-agent-sdk.d.ts.map
@@ -0,0 +1,73 @@
1
+ // kbot ToolDefinition → Anthropic Agent SDK tool
2
+ //
3
+ // One-way schema translation. The Agent SDK delivers tool_use blocks and
4
+ // expects the host to route them to a handler — that routing belongs in the
5
+ // caller's agent loop, not in the adapter. This file only produces the
6
+ // schema half so kbot tools can be advertised to the Agent SDK / Messages
7
+ // API without taking a runtime dependency on @anthropic-ai/sdk.
8
+ const KBOT_TYPE_TO_JSON = {
9
+ string: 'string',
10
+ number: 'number',
11
+ integer: 'integer',
12
+ boolean: 'boolean',
13
+ object: 'object',
14
+ array: 'array',
15
+ null: 'null',
16
+ };
17
+ function mapType(t) {
18
+ const lc = t.toLowerCase();
19
+ return KBOT_TYPE_TO_JSON[lc] ?? 'string';
20
+ }
21
+ function mapParameter(p) {
22
+ const out = {
23
+ type: mapType(p.type),
24
+ description: p.description,
25
+ };
26
+ if (p.default !== undefined)
27
+ out.default = p.default;
28
+ if (p.items)
29
+ out.items = p.items;
30
+ if (p.properties) {
31
+ const nested = {};
32
+ for (const [k, v] of Object.entries(p.properties)) {
33
+ // Best-effort: nested properties in kbot params are loosely typed.
34
+ const vv = v;
35
+ nested[k] = {
36
+ type: vv.type ? mapType(vv.type) : 'string',
37
+ description: vv.description ?? '',
38
+ };
39
+ }
40
+ out.properties = nested;
41
+ }
42
+ return out;
43
+ }
44
+ export function toAgentSdkTool(tool, opts = {}) {
45
+ const properties = {};
46
+ const required = [];
47
+ for (const [name, param] of Object.entries(tool.parameters)) {
48
+ properties[name] = mapParameter(param);
49
+ if (param.required)
50
+ required.push(name);
51
+ }
52
+ const input_schema = {
53
+ type: 'object',
54
+ properties,
55
+ additionalProperties: opts.strict === false ? true : false,
56
+ };
57
+ if (required.length > 0)
58
+ input_schema.required = required;
59
+ const name = opts.renameTool
60
+ ? opts.renameTool(tool.name)
61
+ : opts.preserveName === false
62
+ ? tool.name.replace(/[^A-Za-z0-9_-]/g, '_')
63
+ : tool.name;
64
+ return {
65
+ name,
66
+ description: tool.description,
67
+ input_schema,
68
+ };
69
+ }
70
+ export function toAgentSdkTools(tools, opts = {}) {
71
+ return tools.map((t) => toAgentSdkTool(t, opts));
72
+ }
73
+ //# sourceMappingURL=to-agent-sdk.js.map
@@ -0,0 +1,41 @@
1
+ export type JsonSchemaType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null';
2
+ export interface JsonSchemaProperty {
3
+ type?: JsonSchemaType | JsonSchemaType[];
4
+ description?: string;
5
+ enum?: unknown[];
6
+ items?: JsonSchemaProperty | Record<string, unknown>;
7
+ properties?: Record<string, JsonSchemaProperty>;
8
+ required?: string[];
9
+ default?: unknown;
10
+ [k: string]: unknown;
11
+ }
12
+ export interface AgentSdkInputSchema {
13
+ type: 'object';
14
+ properties: Record<string, JsonSchemaProperty>;
15
+ required?: string[];
16
+ additionalProperties?: boolean;
17
+ }
18
+ /**
19
+ * The on-the-wire tool definition the Agent SDK and the Messages API both
20
+ * accept. Names are snake_case by convention; the SDK does not enforce.
21
+ */
22
+ export interface AgentSdkTool {
23
+ name: string;
24
+ description: string;
25
+ input_schema: AgentSdkInputSchema;
26
+ }
27
+ /**
28
+ * Optional executable companion. The SDK delivers `tool_use` blocks; the
29
+ * caller is responsible for routing them to a handler. `AgentSdkExecutableTool`
30
+ * couples the schema with a handler so the from-adapter can hand back something
31
+ * the kbot registry can run.
32
+ */
33
+ export interface AgentSdkExecutableTool extends AgentSdkTool {
34
+ /**
35
+ * Handler may return a string (passed through) or arbitrary JSON-serializable
36
+ * value (stringified by the adapter). Mirrors what real Agent SDK handlers
37
+ * return in practice.
38
+ */
39
+ handler: (input: Record<string, unknown>) => Promise<unknown> | unknown;
40
+ }
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,9 @@
1
+ // Anthropic Agent SDK tool surface — minimal type model.
2
+ //
3
+ // Mirrors the Tool shape used by @anthropic-ai/sdk and the Agent SDK
4
+ // without taking a runtime dependency. kbot stays provider-agnostic;
5
+ // this adapter only ever speaks JSON Schema and JSON.
6
+ //
7
+ // Reference: https://docs.anthropic.com/en/api/messages#tools
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,42 @@
1
+ import type { PeekabooAgentResult, PeekabooClickResult, PeekabooOutcome, PeekabooPerformActionResult, PeekabooSeeResult, PeekabooSetValueResult, PeekabooTypeResult } from './types.js';
2
+ export interface SeeOptions {
3
+ app?: string;
4
+ mode?: 'screen' | 'window';
5
+ retina?: boolean;
6
+ }
7
+ export declare function see(opts?: SeeOptions): Promise<PeekabooOutcome<PeekabooSeeResult>>;
8
+ export interface ClickOptions {
9
+ snapshot: string;
10
+ on?: string;
11
+ coords?: [number, number];
12
+ wait?: number;
13
+ }
14
+ export declare function click(opts: ClickOptions): Promise<PeekabooOutcome<PeekabooClickResult>>;
15
+ export interface TypeOptions {
16
+ text: string;
17
+ clear?: boolean;
18
+ delayMs?: number;
19
+ }
20
+ export declare function type_(opts: TypeOptions): Promise<PeekabooOutcome<PeekabooTypeResult>>;
21
+ export interface SetValueOptions {
22
+ snapshot: string;
23
+ on: string;
24
+ value: string;
25
+ }
26
+ export declare function setValue(opts: SetValueOptions): Promise<PeekabooOutcome<PeekabooSetValueResult>>;
27
+ export interface PerformActionOptions {
28
+ snapshot: string;
29
+ on: string;
30
+ action: string;
31
+ }
32
+ export declare function performAction(opts: PerformActionOptions): Promise<PeekabooOutcome<PeekabooPerformActionResult>>;
33
+ export interface AgentOptions {
34
+ prompt: string;
35
+ }
36
+ /**
37
+ * Runs `peekaboo agent "$prompt"` and returns the final stdout. Unlike the
38
+ * structured commands the agent subcommand may emit free-form text, so we
39
+ * surface stdout verbatim under `output`.
40
+ */
41
+ export declare function agent(opts: AgentOptions): Promise<PeekabooOutcome<PeekabooAgentResult>>;
42
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1,209 @@
1
+ // Peekaboo high-level helpers — typed wrappers around the JSON CLI.
2
+ //
3
+ // Each helper assembles argv for `peekaboo <subcommand> --json`, runs it
4
+ // through `runPeekaboo`, and parses stdout into the appropriate result
5
+ // type. Non-zero exits and malformed JSON are returned as `PeekabooError`
6
+ // rather than thrown — callers fan out via discriminated unions.
7
+ import { runPeekaboo } from './runner.js';
8
+ function failNonZero(code, stdout, stderr) {
9
+ return {
10
+ ok: false,
11
+ error: {
12
+ code: 'non-zero-exit',
13
+ message: `peekaboo exited ${code}`,
14
+ stdout,
15
+ stderr,
16
+ exitCode: code,
17
+ },
18
+ };
19
+ }
20
+ function failParse(message, stdout) {
21
+ return {
22
+ ok: false,
23
+ error: {
24
+ code: 'malformed-json',
25
+ message,
26
+ stdout,
27
+ },
28
+ };
29
+ }
30
+ function parseJson(stdout) {
31
+ try {
32
+ return { ok: true, value: JSON.parse(stdout) };
33
+ }
34
+ catch (e) {
35
+ return { ok: false, err: failParse(e.message, stdout) };
36
+ }
37
+ }
38
+ function isRecord(v) {
39
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
40
+ }
41
+ function asString(v, fallback = '') {
42
+ return typeof v === 'string' ? v : fallback;
43
+ }
44
+ function asBool(v, fallback = false) {
45
+ return typeof v === 'boolean' ? v : fallback;
46
+ }
47
+ function asNumber(v, fallback = 0) {
48
+ return typeof v === 'number' && Number.isFinite(v) ? v : fallback;
49
+ }
50
+ export async function see(opts = {}) {
51
+ const args = ['see', '--json'];
52
+ if (opts.app)
53
+ args.push('--app', opts.app);
54
+ if (opts.mode)
55
+ args.push('--mode', opts.mode);
56
+ if (opts.retina)
57
+ args.push('--retina');
58
+ const { stdout, stderr, code } = await runPeekaboo(args);
59
+ if (code !== 0)
60
+ return failNonZero(code, stdout, stderr);
61
+ const parsed = parseJson(stdout);
62
+ if (!parsed.ok)
63
+ return parsed.err;
64
+ const v = parsed.value;
65
+ if (!isRecord(v))
66
+ return failParse('see: expected object at root', stdout);
67
+ const rawElements = Array.isArray(v.elements) ? v.elements : [];
68
+ const elements = rawElements.flatMap((el) => {
69
+ if (!isRecord(el))
70
+ return [];
71
+ const frameRaw = isRecord(el.frame) ? el.frame : {};
72
+ return [
73
+ {
74
+ id: asString(el.id),
75
+ role: asString(el.role),
76
+ label: typeof el.label === 'string' ? el.label : undefined,
77
+ frame: {
78
+ x: asNumber(frameRaw.x),
79
+ y: asNumber(frameRaw.y),
80
+ width: asNumber(frameRaw.width),
81
+ height: asNumber(frameRaw.height),
82
+ },
83
+ settable: typeof el.settable === 'boolean' ? el.settable : undefined,
84
+ named_actions: Array.isArray(el.named_actions)
85
+ ? el.named_actions.filter((a) => typeof a === 'string')
86
+ : undefined,
87
+ },
88
+ ];
89
+ });
90
+ return {
91
+ ok: true,
92
+ snapshot: asString(v.snapshot),
93
+ app: typeof v.app === 'string' ? v.app : undefined,
94
+ window: typeof v.window === 'string' ? v.window : undefined,
95
+ elements,
96
+ screenshot_path: typeof v.screenshot_path === 'string' ? v.screenshot_path : undefined,
97
+ };
98
+ }
99
+ export async function click(opts) {
100
+ const args = ['click', '--json', '--snapshot', opts.snapshot];
101
+ if (opts.on)
102
+ args.push('--on', opts.on);
103
+ if (opts.coords)
104
+ args.push('--coords', `${opts.coords[0]},${opts.coords[1]}`);
105
+ if (typeof opts.wait === 'number')
106
+ args.push('--wait', String(opts.wait));
107
+ const { stdout, stderr, code } = await runPeekaboo(args);
108
+ if (code !== 0)
109
+ return failNonZero(code, stdout, stderr);
110
+ const parsed = parseJson(stdout);
111
+ if (!parsed.ok)
112
+ return parsed.err;
113
+ if (!isRecord(parsed.value))
114
+ return failParse('click: expected object at root', stdout);
115
+ const v = parsed.value;
116
+ return {
117
+ ok: true,
118
+ target: typeof v.target === 'string' ? v.target : undefined,
119
+ coords: Array.isArray(v.coords) && v.coords.length === 2
120
+ ? [asNumber(v.coords[0]), asNumber(v.coords[1])]
121
+ : undefined,
122
+ };
123
+ }
124
+ // `type` is reserved in TS; export the helper as `type_`.
125
+ export async function type_(opts) {
126
+ const args = ['type', '--json', '--text', opts.text];
127
+ if (opts.clear)
128
+ args.push('--clear');
129
+ if (typeof opts.delayMs === 'number')
130
+ args.push('--delay', String(opts.delayMs));
131
+ const { stdout, stderr, code } = await runPeekaboo(args);
132
+ if (code !== 0)
133
+ return failNonZero(code, stdout, stderr);
134
+ const parsed = parseJson(stdout);
135
+ if (!parsed.ok)
136
+ return parsed.err;
137
+ if (!isRecord(parsed.value))
138
+ return failParse('type: expected object at root', stdout);
139
+ const v = parsed.value;
140
+ return {
141
+ ok: true,
142
+ typed: asString(v.typed, opts.text),
143
+ cleared: typeof v.cleared === 'boolean' ? v.cleared : undefined,
144
+ };
145
+ }
146
+ export async function setValue(opts) {
147
+ const args = [
148
+ 'set-value',
149
+ '--json',
150
+ '--snapshot',
151
+ opts.snapshot,
152
+ '--on',
153
+ opts.on,
154
+ '--value',
155
+ opts.value,
156
+ ];
157
+ const { stdout, stderr, code } = await runPeekaboo(args);
158
+ if (code !== 0)
159
+ return failNonZero(code, stdout, stderr);
160
+ const parsed = parseJson(stdout);
161
+ if (!parsed.ok)
162
+ return parsed.err;
163
+ if (!isRecord(parsed.value))
164
+ return failParse('set-value: expected object at root', stdout);
165
+ const v = parsed.value;
166
+ return {
167
+ ok: true,
168
+ target: asString(v.target, opts.on),
169
+ value: asString(v.value, opts.value),
170
+ };
171
+ }
172
+ export async function performAction(opts) {
173
+ const args = [
174
+ 'perform-action',
175
+ '--json',
176
+ '--snapshot',
177
+ opts.snapshot,
178
+ '--on',
179
+ opts.on,
180
+ '--action',
181
+ opts.action,
182
+ ];
183
+ const { stdout, stderr, code } = await runPeekaboo(args);
184
+ if (code !== 0)
185
+ return failNonZero(code, stdout, stderr);
186
+ const parsed = parseJson(stdout);
187
+ if (!parsed.ok)
188
+ return parsed.err;
189
+ if (!isRecord(parsed.value))
190
+ return failParse('perform-action: expected object at root', stdout);
191
+ const v = parsed.value;
192
+ return {
193
+ ok: true,
194
+ target: asString(v.target, opts.on),
195
+ action: asString(v.action, opts.action),
196
+ };
197
+ }
198
+ /**
199
+ * Runs `peekaboo agent "$prompt"` and returns the final stdout. Unlike the
200
+ * structured commands the agent subcommand may emit free-form text, so we
201
+ * surface stdout verbatim under `output`.
202
+ */
203
+ export async function agent(opts) {
204
+ const { stdout, stderr, code } = await runPeekaboo(['agent', opts.prompt]);
205
+ if (code !== 0)
206
+ return failNonZero(code, stdout, stderr);
207
+ return { ok: true, output: stdout };
208
+ }
209
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1,4 @@
1
+ export type { PeekabooFrame, PeekabooElement, PeekabooSeeResult, PeekabooClickResult, PeekabooTypeResult, PeekabooSetValueResult, PeekabooPerformActionResult, PeekabooAgentResult, PeekabooError, PeekabooOutcome, } from './types.js';
2
+ export { runPeekaboo, peekabooAvailable, type RunOptions, type RunResult } from './runner.js';
3
+ export { see, click, type_, setValue, performAction, agent, type SeeOptions, type ClickOptions, type TypeOptions, type SetValueOptions, type PerformActionOptions, type AgentOptions, } from './commands.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ // Peekaboo adapter — public surface.
2
+ //
3
+ // Wraps the `peekaboo` macOS CLI behind a typed interface so kbot tools and
4
+ // agents can drive the screen-capture + GUI-automation features without
5
+ // taking a runtime dependency on the binary or the @steipete/peekaboo
6
+ // distribution. All execution flows through `runPeekaboo`.
7
+ export { runPeekaboo, peekabooAvailable } from './runner.js';
8
+ export { see, click, type_, setValue, performAction, agent, } from './commands.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,25 @@
1
+ export interface RunOptions {
2
+ /** Optional stdin payload. */
3
+ input?: string;
4
+ /** Working directory for the child. */
5
+ cwd?: string;
6
+ /** Hard timeout in milliseconds. */
7
+ timeoutMs?: number;
8
+ }
9
+ export interface RunResult {
10
+ stdout: string;
11
+ stderr: string;
12
+ code: number;
13
+ }
14
+ /**
15
+ * Run the peekaboo CLI with the given args. Resolves with stdout/stderr/code
16
+ * regardless of exit status; never rejects on non-zero exit. Rejects only
17
+ * when the binary cannot be spawned at all (ENOENT, permissions, etc.).
18
+ */
19
+ export declare function runPeekaboo(args: string[], opts?: RunOptions): Promise<RunResult>;
20
+ /**
21
+ * Returns true when the peekaboo binary responds to `--version`. Used by
22
+ * higher-level tools to gate Peekaboo features without crashing the host.
23
+ */
24
+ export declare function peekabooAvailable(): Promise<boolean>;
25
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1,75 @@
1
+ // Peekaboo binary runner — thin child_process wrapper.
2
+ //
3
+ // All execution of the `peekaboo` CLI flows through `runPeekaboo`. The
4
+ // binary path is resolved from the PEEKABOO_BIN env var (default: 'peekaboo')
5
+ // so tests can stub it and hosts can pin a specific install. No shell is
6
+ // involved — args go through execFile to keep arg quoting predictable.
7
+ import { execFile } from 'node:child_process';
8
+ function resolveBinary() {
9
+ return process.env.PEEKABOO_BIN && process.env.PEEKABOO_BIN.trim().length > 0
10
+ ? process.env.PEEKABOO_BIN
11
+ : 'peekaboo';
12
+ }
13
+ /**
14
+ * Run the peekaboo CLI with the given args. Resolves with stdout/stderr/code
15
+ * regardless of exit status; never rejects on non-zero exit. Rejects only
16
+ * when the binary cannot be spawned at all (ENOENT, permissions, etc.).
17
+ */
18
+ export function runPeekaboo(args, opts = {}) {
19
+ const bin = resolveBinary();
20
+ return new Promise((resolve, reject) => {
21
+ const child = execFile(bin, args, {
22
+ cwd: opts.cwd,
23
+ timeout: opts.timeoutMs,
24
+ maxBuffer: 64 * 1024 * 1024,
25
+ }, (err, stdout, stderr) => {
26
+ // execFile populates err for non-zero exit too. We surface the result
27
+ // either way and only reject when the spawn itself failed.
28
+ const out = stdout;
29
+ const errOut = stderr;
30
+ const stdoutStr = typeof out === 'string'
31
+ ? out
32
+ : out instanceof Buffer
33
+ ? out.toString('utf8')
34
+ : '';
35
+ const stderrStr = typeof errOut === 'string'
36
+ ? errOut
37
+ : errOut instanceof Buffer
38
+ ? errOut.toString('utf8')
39
+ : '';
40
+ if (err) {
41
+ const errno = err.code;
42
+ // Spawn-level failures (binary missing, EACCES, etc.) reject.
43
+ if (errno === 'ENOENT' || errno === 'EACCES' || errno === 'EPERM') {
44
+ reject(err);
45
+ return;
46
+ }
47
+ // Otherwise treat as "process ran, exited non-zero".
48
+ const code = typeof err.code === 'number'
49
+ ? (err.code)
50
+ : 1;
51
+ resolve({ stdout: stdoutStr, stderr: stderrStr, code });
52
+ return;
53
+ }
54
+ resolve({ stdout: stdoutStr, stderr: stderrStr, code: 0 });
55
+ });
56
+ if (opts.input !== undefined && child.stdin) {
57
+ child.stdin.write(opts.input);
58
+ child.stdin.end();
59
+ }
60
+ });
61
+ }
62
+ /**
63
+ * Returns true when the peekaboo binary responds to `--version`. Used by
64
+ * higher-level tools to gate Peekaboo features without crashing the host.
65
+ */
66
+ export async function peekabooAvailable() {
67
+ try {
68
+ const r = await runPeekaboo(['--version'], { timeoutMs: 5000 });
69
+ return r.code === 0;
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ }
75
+ //# sourceMappingURL=runner.js.map