@thenavidm/apple-photos-mcp-cli 1.1.0 → 2.0.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.
- package/README.md +76 -24
- package/SKILL.md +8 -10
- package/lib/app.d.ts +14 -0
- package/lib/app.js +138 -0
- package/lib/app.js.map +1 -0
- package/lib/bridge.d.ts +6 -6
- package/lib/bridge.js +40 -46
- package/lib/bridge.js.map +1 -1
- package/lib/config.d.ts +6 -4
- package/lib/config.js +19 -25
- package/lib/config.js.map +1 -1
- package/lib/engine.d.ts +44 -0
- package/lib/engine.js +127 -0
- package/lib/engine.js.map +1 -0
- package/lib/errors.d.ts +0 -3
- package/lib/errors.js +0 -3
- package/lib/errors.js.map +1 -1
- package/lib/index.d.ts +10 -6
- package/lib/index.js +17 -104
- package/lib/index.js.map +1 -1
- package/lib/npx.d.ts +2 -0
- package/lib/npx.js +14 -0
- package/lib/npx.js.map +1 -0
- package/lib/tools/index.d.ts +20 -11
- package/lib/tools/index.js +6 -2
- package/lib/tools/index.js.map +1 -1
- package/lib/tools/kit.d.ts +26 -24
- package/lib/tools/kit.js +68 -44
- package/lib/tools/kit.js.map +1 -1
- package/lib/version.d.ts +2 -0
- package/lib/version.js +4 -0
- package/lib/version.js.map +1 -0
- package/package.json +5 -5
- package/lib/cli.d.ts +0 -105
- package/lib/cli.js +0 -644
- package/lib/cli.js.map +0 -1
- package/lib/safety.d.ts +0 -27
- package/lib/safety.js +0 -70
- package/lib/safety.js.map +0 -1
- package/lib/server.d.ts +0 -10
- package/lib/server.js +0 -38
- package/lib/server.js.map +0 -1
- package/src/apple_photos_mcp/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/__main__.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/config.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/doctor.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/library.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/previews.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/safety.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/search.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/server.cpython-313.pyc +0 -0
- package/src/apple_photos_mcp/__pycache__/writes.cpython-313.pyc +0 -0
package/lib/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src-ts/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src-ts/tools/index.ts"],"names":[],"mappings":"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"}
|
package/lib/tools/kit.d.ts
CHANGED
|
@@ -1,30 +1,25 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shared plumbing every tool uses. One spec feeds the MCP server and the CLI,
|
|
3
|
+
* through Slipway, and the HQ connector, which imports `ALL_TOOLS` for its
|
|
4
|
+
* schemas and so keeps this shape: name, title, description, a Zod shape with
|
|
5
|
+
* `confirm` on the one destructive tool, and a risk.
|
|
6
|
+
*/
|
|
7
|
+
import { z, type Risk, type Tool } from "@thenavidm/slipway";
|
|
4
8
|
import type { PythonBridge } from "../bridge.js";
|
|
5
9
|
import type { Config } from "../config.js";
|
|
6
|
-
|
|
10
|
+
export type { Risk };
|
|
11
|
+
/** What every tool runs with: the engine and the settings it was started with. */
|
|
7
12
|
export type ToolContext = {
|
|
8
13
|
bridge: PythonBridge;
|
|
9
14
|
config: Config;
|
|
10
|
-
guard: WriteGuard;
|
|
11
|
-
};
|
|
12
|
-
export type ToolResult = {
|
|
13
|
-
content: {
|
|
14
|
-
type: string;
|
|
15
|
-
text?: string;
|
|
16
|
-
data?: string;
|
|
17
|
-
mimeType?: string;
|
|
18
|
-
}[];
|
|
19
|
-
isError?: boolean;
|
|
20
15
|
};
|
|
21
|
-
export declare function ok(data: unknown): ToolResult;
|
|
22
|
-
export declare function fail(error: unknown): ToolResult;
|
|
23
16
|
export declare const confirmArg: {
|
|
24
17
|
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
25
18
|
};
|
|
26
|
-
export type ToolSpec<S extends ZodRawShape> = {
|
|
19
|
+
export type ToolSpec<S extends z.ZodRawShape> = {
|
|
27
20
|
name: string;
|
|
21
|
+
/** The CLI command, when the name with dashes is one the CLI already uses. */
|
|
22
|
+
command?: string;
|
|
28
23
|
title: string;
|
|
29
24
|
description: string;
|
|
30
25
|
schema: S;
|
|
@@ -36,17 +31,24 @@ export type ToolSpec<S extends ZodRawShape> = {
|
|
|
36
31
|
python?: string;
|
|
37
32
|
summary?: (args: z.infer<z.ZodObject<S>>) => string;
|
|
38
33
|
};
|
|
39
|
-
export declare function defineTool<S extends ZodRawShape>(spec: ToolSpec<S>): ToolSpec<S>;
|
|
40
|
-
export type AnyToolSpec = Omit<ToolSpec<ZodRawShape>, "summary"> & {
|
|
34
|
+
export declare function defineTool<S extends z.ZodRawShape>(spec: ToolSpec<S>): ToolSpec<S>;
|
|
35
|
+
export type AnyToolSpec = Omit<ToolSpec<z.ZodRawShape>, "summary"> & {
|
|
41
36
|
summary?: (args: never) => string;
|
|
42
37
|
};
|
|
43
38
|
/**
|
|
44
|
-
*
|
|
39
|
+
* A failure as the Slipway error that carries its exit code, as 1.1 gave them:
|
|
40
|
+
* an engine that never started is setup, 10; macOS refusing access is 4; a
|
|
41
|
+
* request over a cap is 2; refs that resolve to nothing are 3; anything else
|
|
42
|
+
* the engine reports is 5.
|
|
43
|
+
*/
|
|
44
|
+
export declare function toSlipway(error: unknown): unknown;
|
|
45
|
+
/**
|
|
46
|
+
* Every tool runs the same way: hand the arguments to Python.
|
|
45
47
|
*
|
|
46
48
|
* There is no per-tool handler, because there is nothing per-tool to do. The
|
|
47
|
-
* Python server already implements all thirteen; this layer
|
|
48
|
-
*
|
|
49
|
+
* Python server already implements all thirteen; this layer gives them a
|
|
50
|
+
* second surface, an install story and a schema HQ can import.
|
|
49
51
|
*/
|
|
50
52
|
export declare function runTool(spec: AnyToolSpec, args: Record<string, unknown>, ctx: ToolContext): Promise<unknown>;
|
|
51
|
-
|
|
52
|
-
export
|
|
53
|
+
/** The specs as Slipway tools. `confirm` is Slipway's own, so it leaves each schema here. */
|
|
54
|
+
export declare function slipwayTools(specs: readonly AnyToolSpec[]): Tool<ToolContext>[];
|
package/lib/tools/kit.js
CHANGED
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// leaving a tool whose whole purpose is seeing that returns filenames.
|
|
10
|
-
if (Array.isArray(data) && data.every((p) => p && typeof p === "object" && "type" in p)) {
|
|
11
|
-
return { content: data };
|
|
12
|
-
}
|
|
13
|
-
const text = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
14
|
-
return { content: [{ type: "text", text }] };
|
|
15
|
-
}
|
|
16
|
-
export function fail(error) {
|
|
17
|
-
const payload = error instanceof PhotosError ? error.toJSON() : { error: error?.message ?? String(error) };
|
|
18
|
-
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }], isError: true };
|
|
19
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Shared plumbing every tool uses. One spec feeds the MCP server and the CLI,
|
|
3
|
+
* through Slipway, and the HQ connector, which imports `ALL_TOOLS` for its
|
|
4
|
+
* schemas and so keeps this shape: name, title, description, a Zod shape with
|
|
5
|
+
* `confirm` on the one destructive tool, and a risk.
|
|
6
|
+
*/
|
|
7
|
+
import { ApiError, AuthError, NotConfiguredError, NotFoundError, SlipwayError, UsageError, content, toolkit, z } from "@thenavidm/slipway";
|
|
8
|
+
import { BridgeError, PhotosError, ToolError } from "../errors.js";
|
|
20
9
|
export const confirmArg = {
|
|
21
10
|
confirm: z
|
|
22
11
|
.boolean()
|
|
@@ -27,29 +16,51 @@ export function defineTool(spec) {
|
|
|
27
16
|
return spec;
|
|
28
17
|
}
|
|
29
18
|
/**
|
|
30
|
-
*
|
|
19
|
+
* A failure as the Slipway error that carries its exit code, as 1.1 gave them:
|
|
20
|
+
* an engine that never started is setup, 10; macOS refusing access is 4; a
|
|
21
|
+
* request over a cap is 2; refs that resolve to nothing are 3; anything else
|
|
22
|
+
* the engine reports is 5.
|
|
23
|
+
*/
|
|
24
|
+
export function toSlipway(error) {
|
|
25
|
+
if (error instanceof SlipwayError || !(error instanceof Error))
|
|
26
|
+
return error;
|
|
27
|
+
const text = error.message.toLowerCase();
|
|
28
|
+
const options = error instanceof PhotosError && error.detail ? { details: { detail: error.detail.slice(0, 500) } } : {};
|
|
29
|
+
if (error instanceof BridgeError && /could not start/.test(text))
|
|
30
|
+
return new NotConfiguredError(error.message, options);
|
|
31
|
+
if (/operation not permitted|permission denied|not authori[sz]ed|full disk access|-1743/.test(text))
|
|
32
|
+
return new AuthError(error.message, options);
|
|
33
|
+
if (/at most|too many/.test(text))
|
|
34
|
+
return new UsageError(error.message, options);
|
|
35
|
+
if (/not found|none of those refs resolved|no such/.test(text))
|
|
36
|
+
return new NotFoundError(error.message, options);
|
|
37
|
+
return new ApiError(error.message, options);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Every tool runs the same way: hand the arguments to Python.
|
|
31
41
|
*
|
|
32
42
|
* There is no per-tool handler, because there is nothing per-tool to do. The
|
|
33
|
-
* Python server already implements all thirteen; this layer
|
|
34
|
-
*
|
|
43
|
+
* Python server already implements all thirteen; this layer gives them a
|
|
44
|
+
* second surface, an install story and a schema HQ can import.
|
|
35
45
|
*/
|
|
36
46
|
export async function runTool(spec, args, ctx) {
|
|
37
|
-
if (spec.risk !== "read") {
|
|
38
|
-
const summary = spec.summary?.(args) ?? spec.name;
|
|
39
|
-
ctx.guard.check(spec.name, spec.risk, args.confirm, summary);
|
|
40
|
-
}
|
|
41
47
|
// Only undefined and null are dropped. An empty string is a real value here:
|
|
42
48
|
// clearing a caption is `set_photo_description --description ""`, and
|
|
43
49
|
// stripping it made the engine reject the call for a missing required
|
|
44
50
|
// argument the caller had plainly supplied.
|
|
45
51
|
const payload = Object.fromEntries(Object.entries(args).filter(([, v]) => v !== undefined && v !== null));
|
|
52
|
+
// Slipway lets an irreversible call reach this point only once it is
|
|
53
|
+
// confirmed, and the engine asks for the same confirmation in its own words.
|
|
54
|
+
if (spec.risk === "destructive")
|
|
55
|
+
payload.confirm = true;
|
|
46
56
|
const result = await ctx.bridge.call(spec.python ?? spec.name, payload, spec.timeoutMs);
|
|
47
57
|
if (result.isError)
|
|
48
58
|
throw new ToolError(result.text || `${spec.name} failed.`);
|
|
49
|
-
// Anything that is not plain text
|
|
50
|
-
// as content parts
|
|
59
|
+
// Anything that is not plain text, the images from look_at_photos, goes back
|
|
60
|
+
// as content parts, and the CLI prints the same parts as JSON, which is what
|
|
61
|
+
// the HQ agent hands back to the hosted connector.
|
|
51
62
|
if (result.content.some((part) => part.type !== "text"))
|
|
52
|
-
return result.content;
|
|
63
|
+
return content(result.content, result.content);
|
|
53
64
|
let parsed;
|
|
54
65
|
try {
|
|
55
66
|
parsed = JSON.parse(result.text);
|
|
@@ -68,20 +79,33 @@ export async function runTool(spec, args, ctx) {
|
|
|
68
79
|
}
|
|
69
80
|
return parsed;
|
|
70
81
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
const kit = toolkit();
|
|
83
|
+
/** The specs as Slipway tools. `confirm` is Slipway's own, so it leaves each schema here. */
|
|
84
|
+
export function slipwayTools(specs) {
|
|
85
|
+
return specs.map((spec) => {
|
|
86
|
+
const { confirm: _confirm, ...shape } = spec.schema;
|
|
87
|
+
return kit.defineTool({
|
|
88
|
+
name: spec.name,
|
|
89
|
+
...(spec.command ? { command: spec.command } : {}),
|
|
90
|
+
title: spec.title,
|
|
91
|
+
description: spec.description,
|
|
92
|
+
input: z.object(shape),
|
|
93
|
+
risk: spec.risk,
|
|
94
|
+
...(spec.idempotent === undefined ? {} : { idempotent: spec.idempotent }),
|
|
95
|
+
// Everything stays on this Mac: no network, no upload, nothing leaves.
|
|
96
|
+
openWorld: false,
|
|
97
|
+
// 1.1's words for the one destructive tool's refusal.
|
|
98
|
+
...(spec.risk === "destructive" ? { consequence: "cannot be undone from here" } : {}),
|
|
99
|
+
...(spec.summary ? { summary: spec.summary } : {}),
|
|
100
|
+
handler: async (args, ctx) => {
|
|
101
|
+
try {
|
|
102
|
+
return await runTool(spec, args, ctx);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw toSlipway(error);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
});
|
|
85
110
|
}
|
|
86
|
-
export { needsConfirm };
|
|
87
111
|
//# sourceMappingURL=kit.js.map
|
package/lib/tools/kit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kit.js","sourceRoot":"","sources":["../../src-ts/tools/kit.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"kit.js","sourceRoot":"","sources":["../../src-ts/tools/kit.ts"],"names":[],"mappings":"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"}
|
package/lib/version.d.ts
ADDED
package/lib/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src-ts/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,mGAAmG;AACnG,MAAM,CAAC,MAAM,OAAO,GAAY,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thenavidm/apple-photos-mcp-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Apple Photos MCP server and CLI for Claude Code and AI agents. 13 tools to search, look at, organise and export your own Photos library, entirely on your Mac.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"apple-photos-mcp": "lib/index.js",
|
|
9
|
-
"apple-photos-cli": "lib/index.js"
|
|
9
|
+
"apple-photos-cli": "lib/index.js",
|
|
10
|
+
"apple-photos-mcp-cli": "lib/npx.js"
|
|
10
11
|
},
|
|
11
12
|
"engines": {
|
|
12
|
-
"node": ">=
|
|
13
|
+
"node": ">=22"
|
|
13
14
|
},
|
|
14
15
|
"scripts": {
|
|
15
16
|
"build": "tsc",
|
|
@@ -19,8 +20,7 @@
|
|
|
19
20
|
"build:mcpb": "bash desktop-extension/build.sh"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"zod": "^3.23.8"
|
|
23
|
+
"@thenavidm/slipway": "^0.1.24"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^22.10.0",
|
package/lib/cli.d.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The CLI adapter.
|
|
3
|
-
*
|
|
4
|
-
* `register()` in tools/kit.ts turns a `ToolSpec` into an MCP tool. This turns
|
|
5
|
-
* the same spec into a shell command, from the same `ALL_TOOLS` array, through
|
|
6
|
-
* the same handler and the same `WriteGuard`. Nothing is described twice, so a
|
|
7
|
-
* tool added tomorrow is a command tomorrow and the two surfaces cannot drift.
|
|
8
|
-
*
|
|
9
|
-
* The command IS the tool name. `submit_imagine` runs as `submit-imagine`, and
|
|
10
|
-
* the underscore form works too. Inventing a prettier command tree would mean a
|
|
11
|
-
* hand-written mapping, which is exactly the drift this avoids, and it would
|
|
12
|
-
* force anyone reading the SKILL.md to learn two vocabularies for one action.
|
|
13
|
-
*
|
|
14
|
-
* Zod is the only schema: every flag, its placeholder, its help text and its
|
|
15
|
-
* validation come from the shape the MCP tool already declares.
|
|
16
|
-
*/
|
|
17
|
-
import { type ZodRawShape } from "zod";
|
|
18
|
-
import { type AnyToolSpec } from "./tools/kit.js";
|
|
19
|
-
/** How a value reaches the parser, once the Zod wrappers are peeled off. */
|
|
20
|
-
type FlagKind = "string" | "number" | "boolean" | "enum" | "json";
|
|
21
|
-
type Flag = {
|
|
22
|
-
key: string;
|
|
23
|
-
flag: string;
|
|
24
|
-
kind: FlagKind;
|
|
25
|
-
required: boolean;
|
|
26
|
-
repeatable: boolean;
|
|
27
|
-
choices?: string[];
|
|
28
|
-
help: string;
|
|
29
|
-
};
|
|
30
|
-
export declare function flagsFor(shape: ZodRawShape): Flag[];
|
|
31
|
-
/** Shorthands for this repo's arguments. Kept small on purpose. */
|
|
32
|
-
export declare const FLAG_ALIASES: Record<string, string>;
|
|
33
|
-
/**
|
|
34
|
-
* Parse argv against a tool's flags.
|
|
35
|
-
*
|
|
36
|
-
* Zod does the real validation afterwards, so this only has to get values into
|
|
37
|
-
* the right JavaScript types and catch the mistakes Zod would otherwise report
|
|
38
|
-
* in terms of a schema the person at the terminal never sees.
|
|
39
|
-
*/
|
|
40
|
-
export declare function parseArgs(argv: string[], flags: Flag[]): Record<string, unknown>;
|
|
41
|
-
/**
|
|
42
|
-
* Keep only the named fields.
|
|
43
|
-
*
|
|
44
|
-
* These endpoints are verbose: one explore page is tens of kilobytes of JSON,
|
|
45
|
-
* most of it layout hints. An agent piping that into its own context pays for
|
|
46
|
-
* every byte. `--select id,status,images` cuts it to what was asked for.
|
|
47
|
-
* Dotted paths descend, and arrays are traversed element-wise.
|
|
48
|
-
*/
|
|
49
|
-
export declare function selectFields(data: unknown, paths: string[]): unknown;
|
|
50
|
-
/** Errors are JSON on stderr, always, so a caller parses one shape. */
|
|
51
|
-
export declare function emitError(error: unknown): void;
|
|
52
|
-
/**
|
|
53
|
-
* The name this was invoked as, so examples are copy-pasteable.
|
|
54
|
-
*
|
|
55
|
-
* The package puts two binaries on the same file. Printing `apple-photos-mcp` at
|
|
56
|
-
* someone who typed `apple-photos-cli` hands them a command that works but is not
|
|
57
|
-
* the one in their fingers.
|
|
58
|
-
*/
|
|
59
|
-
export declare function binName(): string;
|
|
60
|
-
/**
|
|
61
|
-
* Words people use mapped onto words these tools use.
|
|
62
|
-
*
|
|
63
|
-
* Without this, "save my photos to disk" matches four browsing tools and never
|
|
64
|
-
* export-originals, because nothing in that phrase appears in its name or
|
|
65
|
-
* description. Every target below has to be vocabulary a tool actually
|
|
66
|
-
* contains; a test asserts it.
|
|
67
|
-
*/
|
|
68
|
-
export declare const SYNONYMS: Record<string, string[]>;
|
|
69
|
-
/**
|
|
70
|
-
* Resolve a capability described in words to the command that does it.
|
|
71
|
-
*
|
|
72
|
-
* An agent that knows what it wants but not what this tool calls it would
|
|
73
|
-
* otherwise read the full tool list to find out, which is the cost the CLI
|
|
74
|
-
* exists to avoid. Scoring is deliberately dumb: name and title carry the most
|
|
75
|
-
* weight, because a tool called `download_job` should win "download my images"
|
|
76
|
-
* without any cleverness.
|
|
77
|
-
*/
|
|
78
|
-
export declare function whichCommand(query: string): {
|
|
79
|
-
tool: AnyToolSpec;
|
|
80
|
-
score: number;
|
|
81
|
-
}[];
|
|
82
|
-
/**
|
|
83
|
-
* The house contract, so a script branches on the number the same way for
|
|
84
|
-
* every one of these CLIs: 0 ok, 2 usage or a refused write, 3 not found,
|
|
85
|
-
* 4 access refused, 5 the engine failed, 10 nothing set up yet.
|
|
86
|
-
*/
|
|
87
|
-
export declare const EXIT: {
|
|
88
|
-
readonly ok: 0;
|
|
89
|
-
readonly usage: 2;
|
|
90
|
-
readonly notFound: 3;
|
|
91
|
-
readonly auth: 4;
|
|
92
|
-
readonly api: 5;
|
|
93
|
-
readonly rateLimited: 7;
|
|
94
|
-
readonly config: 10;
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* There is no account here, so "auth" is macOS refusing access: Full Disk
|
|
98
|
-
* Access for the library, or Automation for Photos itself. The engine reports
|
|
99
|
-
* its failures as text, so its words decide once the class has said what it
|
|
100
|
-
* can.
|
|
101
|
-
*/
|
|
102
|
-
export declare function exitCodeFor(error: unknown): number;
|
|
103
|
-
export declare function isCliCommand(argv: string[]): boolean;
|
|
104
|
-
export declare function runCli(argv: string[]): Promise<number>;
|
|
105
|
-
export {};
|