things-api 0.17.0 → 0.19.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 +16 -9
- package/deputy/AppIcon.icns +0 -0
- package/deputy/VERSION +1 -0
- package/deputy/helpers-Info.plist +27 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +22 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Resources/AppIcon.icns +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +128 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +27 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Resources/AppIcon.icns +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +137 -0
- package/deputy/reader/Info.plist +22 -0
- package/deputy/reader/entitlements.plist +45 -0
- package/deputy/reader/main.swift +580 -0
- package/deputy/src/main.swift +133 -0
- package/deputy/src/osascript.swift +102 -0
- package/deputy/src/server.swift +373 -0
- package/deputy/src/sqlite.swift +121 -0
- package/deputy/src/tcc.swift +58 -0
- package/dist/audit/schema.d.ts +13 -1
- package/dist/audit/schema.js.map +1 -1
- package/dist/capability.d.ts +160 -0
- package/dist/capability.js +416 -0
- package/dist/capability.js.map +1 -0
- package/dist/cli/commands/doctor.js +181 -2
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/helpers.d.ts +17 -0
- package/dist/cli/commands/helpers.js +275 -0
- package/dist/cli/commands/helpers.js.map +1 -0
- package/dist/cli/commands/op-result.d.ts +15 -0
- package/dist/cli/commands/op-result.js +45 -0
- package/dist/cli/commands/op-result.js.map +1 -0
- package/dist/cli/commands/reads.js +47 -1
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +9 -0
- package/dist/cli/commands/setup.js +63 -83
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/writes.d.ts +1 -1
- package/dist/cli/commands/writes.js +262 -109
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/dry-run.d.ts +1 -1
- package/dist/cli/dry-run.js +1 -1
- package/dist/cli/glyphs.d.ts +23 -4
- package/dist/cli/glyphs.js +46 -19
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +53 -27
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/helpers-check.d.ts +10 -0
- package/dist/cli/helpers-check.js +59 -0
- package/dist/cli/helpers-check.js.map +1 -0
- package/dist/cli/main.js +22 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/period.d.ts +3 -1
- package/dist/cli/period.js +1 -1
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.js +26 -1
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +31 -4
- package/dist/cli/render.js +127 -15
- package/dist/cli/render.js.map +1 -1
- package/dist/client.d.ts +22 -2
- package/dist/client.js +52 -15
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +31 -0
- package/dist/config.js +9 -0
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +6 -2
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/baselines/db-v26.js +8 -4
- package/dist/db/baselines/db-v26.js.map +1 -1
- package/dist/db/baselines/db-v27.d.ts +42 -0
- package/dist/db/baselines/db-v27.js +47 -0
- package/dist/db/baselines/db-v27.js.map +1 -0
- package/dist/db/baselines/index.js +2 -1
- package/dist/db/baselines/index.js.map +1 -1
- package/dist/db/locate.d.ts +4 -1
- package/dist/db/locate.js +3 -1
- package/dist/db/locate.js.map +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +9 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/deputy/bridge-worker.d.ts +1 -0
- package/dist/deputy/bridge-worker.js +79 -0
- package/dist/deputy/bridge-worker.js.map +1 -0
- package/dist/deputy/bridge.d.ts +14 -0
- package/dist/deputy/bridge.js +70 -0
- package/dist/deputy/bridge.js.map +1 -0
- package/dist/deputy/client.d.ts +19 -0
- package/dist/deputy/client.js +104 -0
- package/dist/deputy/client.js.map +1 -0
- package/dist/deputy/db-facade.d.ts +18 -0
- package/dist/deputy/db-facade.js +71 -0
- package/dist/deputy/db-facade.js.map +1 -0
- package/dist/deputy/files.d.ts +1 -0
- package/dist/deputy/files.js +16 -0
- package/dist/deputy/files.js.map +1 -0
- package/dist/deputy/install.d.ts +319 -0
- package/dist/deputy/install.js +1239 -0
- package/dist/deputy/install.js.map +1 -0
- package/dist/deputy/notice.d.ts +6 -0
- package/dist/deputy/notice.js +28 -0
- package/dist/deputy/notice.js.map +1 -0
- package/dist/deputy/notices.d.ts +31 -0
- package/dist/deputy/notices.js +94 -0
- package/dist/deputy/notices.js.map +1 -0
- package/dist/deputy/osa.d.ts +21 -0
- package/dist/deputy/osa.js +72 -0
- package/dist/deputy/osa.js.map +1 -0
- package/dist/deputy/protocol.d.ts +140 -0
- package/dist/deputy/protocol.js +143 -0
- package/dist/deputy/protocol.js.map +1 -0
- package/dist/deputy/routing.d.ts +84 -0
- package/dist/deputy/routing.js +422 -0
- package/dist/deputy/routing.js.map +1 -0
- package/dist/deputy/shortcuts-exec.d.ts +10 -0
- package/dist/deputy/shortcuts-exec.js +50 -0
- package/dist/deputy/shortcuts-exec.js.map +1 -0
- package/dist/diagnose.d.ts +57 -2
- package/dist/diagnose.js +105 -3
- package/dist/diagnose.js.map +1 -1
- package/dist/direct-setup.d.ts +78 -0
- package/dist/direct-setup.js +484 -0
- package/dist/direct-setup.js.map +1 -0
- package/dist/host-access.d.ts +63 -0
- package/dist/host-access.js +165 -0
- package/dist/host-access.js.map +1 -0
- package/dist/index.d.ts +31 -5
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +27 -1
- package/dist/mcp/server.js +300 -97
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/mappers.d.ts +12 -3
- package/dist/model/mappers.js +6 -1
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/recurrence.d.ts +5 -1
- package/dist/model/recurrence.js +19 -1
- package/dist/model/recurrence.js.map +1 -1
- package/dist/model/template-projection.d.ts +26 -0
- package/dist/model/template-projection.js +113 -0
- package/dist/model/template-projection.js.map +1 -0
- package/dist/op-result.d.ts +55 -0
- package/dist/op-result.js +161 -0
- package/dist/op-result.js.map +1 -0
- package/dist/read/detail.js +7 -1
- package/dist/read/detail.js.map +1 -1
- package/dist/read/filter-contract.d.ts +1 -1
- package/dist/read/filter-contract.js +4 -0
- package/dist/read/filter-contract.js.map +1 -1
- package/dist/read/queries.js +8 -1
- package/dist/read/queries.js.map +1 -1
- package/dist/read/shape.js +4 -0
- package/dist/read/shape.js.map +1 -1
- package/dist/read/views.d.ts +35 -4
- package/dist/read/views.js +120 -18
- package/dist/read/views.js.map +1 -1
- package/dist/session-grant.d.ts +48 -0
- package/dist/session-grant.js +170 -0
- package/dist/session-grant.js.map +1 -0
- package/dist/surface-copy.d.ts +8 -0
- package/dist/surface-copy.js +8 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/sync-health.js +6 -2
- package/dist/sync-health.js.map +1 -1
- package/dist/wizard.d.ts +58 -0
- package/dist/wizard.js +167 -0
- package/dist/wizard.js.map +1 -0
- package/dist/write/accessibility-probe.js +4 -2
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.js +5 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/availability.d.ts +1 -1
- package/dist/write/availability.js +10 -6
- package/dist/write/availability.js.map +1 -1
- package/dist/write/batch.d.ts +20 -0
- package/dist/write/batch.js +94 -15
- package/dist/write/batch.js.map +1 -1
- package/dist/write/capabilities.d.ts +9 -0
- package/dist/write/capabilities.js +2 -0
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/clear-reminder.js +1 -1
- package/dist/write/clear-reminder.js.map +1 -1
- package/dist/write/commands.d.ts +12 -1
- package/dist/write/commands.js +170 -237
- package/dist/write/commands.js.map +1 -1
- package/dist/write/experimental.d.ts +19 -0
- package/dist/write/experimental.js +50 -0
- package/dist/write/experimental.js.map +1 -1
- package/dist/write/failure-hints.d.ts +3 -1
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.js +19 -2
- package/dist/write/guards.js.map +1 -1
- package/dist/write/lock.d.ts +16 -13
- package/dist/write/lock.js +55 -0
- package/dist/write/lock.js.map +1 -1
- package/dist/write/make-repeating-project.js +9 -13
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/move.js +14 -6
- package/dist/write/move.js.map +1 -1
- package/dist/write/operations.d.ts +64 -25
- package/dist/write/operations.js +7 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +14 -0
- package/dist/write/opid.js +22 -0
- package/dist/write/opid.js.map +1 -1
- package/dist/write/param-schema.d.ts +124 -0
- package/dist/write/param-schema.js +747 -0
- package/dist/write/param-schema.js.map +1 -0
- package/dist/write/pipeline.d.ts +78 -2
- package/dist/write/pipeline.js +249 -4
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +8 -0
- package/dist/write/pre-state.js +62 -17
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/promote-clone.js +635 -367
- package/dist/write/promote-clone.js.map +1 -1
- package/dist/write/reorder.js +95 -29
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-anchor.d.ts +30 -0
- package/dist/write/repeat-anchor.js +166 -1
- package/dist/write/repeat-anchor.js.map +1 -1
- package/dist/write/repeat-rule.d.ts +28 -1
- package/dist/write/repeat-rule.js +64 -4
- package/dist/write/repeat-rule.js.map +1 -1
- package/dist/write/resolution-timestamps.d.ts +11 -0
- package/dist/write/resolution-timestamps.js +83 -38
- package/dist/write/resolution-timestamps.js.map +1 -1
- package/dist/write/reversibility.js +4 -0
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/template-mutation.d.ts +137 -0
- package/dist/write/template-mutation.js +451 -0
- package/dist/write/template-mutation.js.map +1 -0
- package/dist/write/undo.js +10 -20
- package/dist/write/undo.js.map +1 -1
- package/dist/write/update-fields.d.ts +151 -0
- package/dist/write/update-fields.js +427 -0
- package/dist/write/update-fields.js.map +1 -0
- package/dist/write/vectors/applescript.js +10 -16
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +1 -1
- package/dist/write/vectors/registry.js +10 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/session-reachability.d.ts +55 -0
- package/dist/write/vectors/session-reachability.js +56 -8
- package/dist/write/vectors/session-reachability.js.map +1 -1
- package/dist/write/vectors/shortcuts.js +7 -16
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +16 -1
- package/dist/write/vectors/simulator.js +68 -12
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +124 -1
- package/dist/write/vectors/ui-recipes.d.ts +19 -0
- package/dist/write/vectors/ui-recipes.js +158 -38
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +89 -0
- package/dist/write/vectors/ui.js +504 -49
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +21 -0
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +13 -0
- package/dist/write/verify/poller.js +38 -0
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +9 -1
- package/schema/envelope.schema.json +5 -3
- package/scripts/build-helpers.sh +109 -0
- package/scripts/deputy-cert-setup.sh +60 -0
- package/skills/things-cli/SKILL.md +12 -5
- package/skills/things-cli/references/contracts.md +1 -0
- package/skills/things-cli/references/data-model.md +3 -0
- package/skills/things-cli/references/errors.md +5 -1
- package/skills/things-cli/references/gui.md +1 -0
- package/skills/things-cli/references/repeating.md +75 -0
- package/skills/things-cli/references/tag-cleanup.md +64 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { type HelpersMode } from "../config.ts";
|
|
2
|
+
import { type Wizard } from "../wizard.ts";
|
|
3
|
+
import { type DeputyHello } from "./protocol.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Where the LaunchAgent plists live. THINGS_API_LAUNCH_AGENTS_DIR overrides
|
|
6
|
+
* for tests — WITHOUT it, every suite that exercises install/uninstall/reset
|
|
7
|
+
* mutates the DEVELOPER MACHINE's real ~/Library/LaunchAgents. That is not
|
|
8
|
+
* hypothetical: it deleted the live helpers' plists mid-`npm run check`
|
|
9
|
+
* twice on 2026-08-24 before this seam existed. Test setup must always set
|
|
10
|
+
* it alongside THINGS_API_STATE_DIR.
|
|
11
|
+
*/
|
|
12
|
+
export declare function launchAgentsDir(env?: NodeJS.ProcessEnv): string;
|
|
13
|
+
export declare function deputyPlistPath(env?: NodeJS.ProcessEnv): string;
|
|
14
|
+
export declare function readerPlistPath(env?: NodeJS.ProcessEnv): string;
|
|
15
|
+
/**
|
|
16
|
+
* Where an install looks for the bundle when the caller names no path, in
|
|
17
|
+
* preference order: `deputy/prebuilt` — the signed + notarized bundle the
|
|
18
|
+
* release workflow stages into the published tarball, so an npm install needs
|
|
19
|
+
* neither Xcode nor a certificate — then `deputy/build`, the output of
|
|
20
|
+
* scripts/build-helpers.sh in a source checkout.
|
|
21
|
+
*/
|
|
22
|
+
export declare function helpersBundleCandidates(): string[];
|
|
23
|
+
/**
|
|
24
|
+
* The first candidate bundle that carries a deputy executable; null when none
|
|
25
|
+
* does. Both candidates are READ only — nothing in the `things helpers` path
|
|
26
|
+
* ever writes inside the package directory, so the CLI works from a read-only
|
|
27
|
+
* package root (an npx cache); BUILDING a bundle there is the one operation
|
|
28
|
+
* that needs a writable checkout, and `--bundle <path>` covers a prebuilt one.
|
|
29
|
+
*/
|
|
30
|
+
export declare function helpersDefaultBuildPath(): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* The INSTALLED bundle's version, read prompt-free from its Info.plist
|
|
33
|
+
* (CFBundleShortVersionString, stamped from deputy/VERSION at build time).
|
|
34
|
+
* Null when nothing is installed or the plist is unreadable/unstamped. This is
|
|
35
|
+
* the version a passive upgrade notice compares against
|
|
36
|
+
* {@link EXPECTED_HELPERS_VERSION} without needing a running helper.
|
|
37
|
+
*/
|
|
38
|
+
export declare function installedHelpersVersion(env?: NodeJS.ProcessEnv): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* The reader's LaunchAgent. Two keys carry the whole host-universal rendezvous:
|
|
41
|
+
*
|
|
42
|
+
* - **`Sockets`** — launchd creates, binds, listens on and chmods the socket at
|
|
43
|
+
* `socketPath`, which is OUR state directory, and hands the sandboxed reader
|
|
44
|
+
* the already-listening fd at activation (`launch_activate_socket`). The
|
|
45
|
+
* reader cannot bind outside its container, so launchd binding on its behalf
|
|
46
|
+
* is the only way the rendezvous escapes it — and with the socket outside
|
|
47
|
+
* every container, a client reaching it crosses no consent class.
|
|
48
|
+
* - **`EnvironmentVariables`** — the access token, minted by the installer and
|
|
49
|
+
* written to a sibling file for clients. Delivering it through the plist is
|
|
50
|
+
* what lets the reader keep its expected token out of the container too.
|
|
51
|
+
*
|
|
52
|
+
* The plist therefore CARRIES A SECRET and is written 0600 — the same
|
|
53
|
+
* same-user trust class as the token file itself.
|
|
54
|
+
*/
|
|
55
|
+
export declare function renderReaderPlist(appPath: string, socketPath: string, token: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Mint the reader's access token and lay down the client half of the
|
|
58
|
+
* rendezvous: `<state>/reader`, 0700, holding a 0600 token file. Returns the
|
|
59
|
+
* token so the same value can be injected into the LaunchAgent.
|
|
60
|
+
*
|
|
61
|
+
* The installer mints it — not the reader — because the reader can only write
|
|
62
|
+
* inside its container, which is the placement this whole arrangement exists
|
|
63
|
+
* to leave. A fresh token per install is deliberate: install owns the pair
|
|
64
|
+
* wholesale, and rotating the secret costs nothing when both ends are rewritten
|
|
65
|
+
* in the same breath.
|
|
66
|
+
*/
|
|
67
|
+
export declare function mintReaderRendezvous(env: NodeJS.ProcessEnv): string;
|
|
68
|
+
export interface DeputySigning {
|
|
69
|
+
state: "signed" | "adhoc" | "unsigned" | "unknown";
|
|
70
|
+
authority: string | null;
|
|
71
|
+
}
|
|
72
|
+
/** codesign facts about a binary (diagnostic output — may name mechanisms). */
|
|
73
|
+
export declare function deputySigningInfo(binaryPath: string): DeputySigning;
|
|
74
|
+
export interface HelpersInstallResult {
|
|
75
|
+
bundlePath: string;
|
|
76
|
+
plistPath: string;
|
|
77
|
+
stateDir: string;
|
|
78
|
+
signing: DeputySigning;
|
|
79
|
+
readerInstalled: boolean;
|
|
80
|
+
/** Reader grant state after install: null when the reader is absent or never answered. */
|
|
81
|
+
readerGranted: boolean | null;
|
|
82
|
+
warnings: string[];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Install (or reinstall) the helpers: copy the built bundle to its stable
|
|
86
|
+
* path, write both LaunchAgent plists, and (re)bootstrap them under launchd.
|
|
87
|
+
*/
|
|
88
|
+
export declare function installHelpers(options?: {
|
|
89
|
+
bundlePath?: string;
|
|
90
|
+
}, env?: NodeJS.ProcessEnv): HelpersInstallResult;
|
|
91
|
+
export interface HelpersRevocation {
|
|
92
|
+
/** One row per macOS permission-store reset attempted. */
|
|
93
|
+
tccResets: {
|
|
94
|
+
target: string;
|
|
95
|
+
ok: boolean;
|
|
96
|
+
detail: string;
|
|
97
|
+
}[];
|
|
98
|
+
/**
|
|
99
|
+
* What made the identifiers resolvable for `tccutil`: the bundle this
|
|
100
|
+
* machine had installed, the packaged bundle registered on the spot, or
|
|
101
|
+
* nothing at all (the grants cannot be addressed from here).
|
|
102
|
+
*/
|
|
103
|
+
resolvedVia: "installed" | "packaged" | "none";
|
|
104
|
+
/** The packaged bundle handed to LaunchServices, when that path was taken. */
|
|
105
|
+
registeredBundle: string | null;
|
|
106
|
+
/** The one leg no tool can perform — surfaced, never silently skipped. */
|
|
107
|
+
shortcutsNote: string;
|
|
108
|
+
}
|
|
109
|
+
export interface HelpersUninstallResult {
|
|
110
|
+
/** Files/directories that existed and were removed. */
|
|
111
|
+
removed: string[];
|
|
112
|
+
/** Null unless revocation was asked for. */
|
|
113
|
+
revocation: HelpersRevocation | null;
|
|
114
|
+
warnings: string[];
|
|
115
|
+
}
|
|
116
|
+
export interface HelpersUninstallOptions {
|
|
117
|
+
/**
|
|
118
|
+
* Also revoke both identities' macOS permission grants and delete their
|
|
119
|
+
* local state (the reader's bookmark container, the deputy's tokens/logs).
|
|
120
|
+
*/
|
|
121
|
+
revoke?: boolean;
|
|
122
|
+
}
|
|
123
|
+
export interface HelpersUninstallDeps {
|
|
124
|
+
/** External tool runner (test seam — a real `tccutil` revokes live grants). */
|
|
125
|
+
runTool?: (bin: string, args: string[]) => {
|
|
126
|
+
ok: boolean;
|
|
127
|
+
output: string;
|
|
128
|
+
};
|
|
129
|
+
/** Where a packaged bundle lives for the LaunchServices fallback. */
|
|
130
|
+
packagedBundlePath?: () => string | null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Stop both halves and remove their LaunchAgents + the installed bundle.
|
|
134
|
+
*
|
|
135
|
+
* By default the macOS grants and the local state (tokens, logs, the reader's
|
|
136
|
+
* bookmark) are KEPT: the TCC rows are keyed to the two signing identities and
|
|
137
|
+
* simply go dormant, so a later reinstall picks them straight back up with no
|
|
138
|
+
* second ceremony. `revoke` turns this into the ceremony's full inverse —
|
|
139
|
+
* grants revoked first (see {@link revokeGrants}), then the uninstall, then the
|
|
140
|
+
* reader's container and the deputy's state dir deleted (the read grant is a
|
|
141
|
+
* bookmark FILE, not a TCC row, so revoking it means deleting it).
|
|
142
|
+
*
|
|
143
|
+
* Every leg is independent and IDEMPOTENT: an already-uninstalled helper, an
|
|
144
|
+
* empty permission store, and absent directories are all fine — each leg does
|
|
145
|
+
* whatever is still outstanding, so this works from any partial state and a
|
|
146
|
+
* second run is an all-no-op.
|
|
147
|
+
*/
|
|
148
|
+
export declare function uninstallHelpers(options?: HelpersUninstallOptions, env?: NodeJS.ProcessEnv, deps?: HelpersUninstallDeps): HelpersUninstallResult;
|
|
149
|
+
/** Restart the launchd-managed helpers (picks up a rebuilt installed bundle). */
|
|
150
|
+
export declare function restartHelpers(): void;
|
|
151
|
+
/**
|
|
152
|
+
* The one-time grant ceremony: open the reader in `--grant` mode (the panel
|
|
153
|
+
* must be presented by the SANDBOXED process — that is what makes the grant
|
|
154
|
+
* durable) and wait for the bookmark to land, confirmed via the reader's
|
|
155
|
+
* handshake. The panel opens INSIDE the Things data folder when it exists, so
|
|
156
|
+
* accepting is the only click. Interactive by design; returns when granted or
|
|
157
|
+
* on timeout, and verifies the database actually resolves inside the granted
|
|
158
|
+
* scope so a wrong-folder grant reports loudly instead of half-working.
|
|
159
|
+
*/
|
|
160
|
+
export declare function grantReader(env?: NodeJS.ProcessEnv): {
|
|
161
|
+
granted: boolean;
|
|
162
|
+
detail: string;
|
|
163
|
+
};
|
|
164
|
+
export type OnboardLeg = "reader-read-grant" | "automation-things" | "automation-system-events" | "accessibility" | "shortcuts";
|
|
165
|
+
/**
|
|
166
|
+
* Which TIER a leg belongs to (docs/design/permissions-doctrine.md, Article V).
|
|
167
|
+
* The BASE tier gathers read + write capability, which is what every consumer
|
|
168
|
+
* of this package needs. The GUI tier adds the two grants that let the helpers
|
|
169
|
+
* drive the Things WINDOW — Accessibility and Automation → System Events — and
|
|
170
|
+
* is only gathered when it was asked for, because those two are the widest
|
|
171
|
+
* grants the pair ever holds and most households never need them.
|
|
172
|
+
*/
|
|
173
|
+
export type OnboardTier = "base" | "gui";
|
|
174
|
+
/**
|
|
175
|
+
* Where a leg stands after the ceremony. `pending` is a HUMAN-pace outcome (a
|
|
176
|
+
* dialog left unanswered, a toggle not yet flipped) and is not a failure —
|
|
177
|
+
* rerunning resumes exactly where it stopped. Only `denied` means macOS (or
|
|
178
|
+
* the user) refused, and only that makes the command exit nonzero.
|
|
179
|
+
*/
|
|
180
|
+
export type OnboardState = "granted" | "denied" | "pending" | "skipped-not-installed";
|
|
181
|
+
export interface OnboardStep {
|
|
182
|
+
leg: OnboardLeg;
|
|
183
|
+
/** The row label in the closing report. */
|
|
184
|
+
label: string;
|
|
185
|
+
/** The tier this leg belongs to — `gui` legs run only when that tier is in. */
|
|
186
|
+
tier: OnboardTier;
|
|
187
|
+
state: OnboardState;
|
|
188
|
+
/** True when the leg was already satisfied, detected without raising anything. */
|
|
189
|
+
alreadyGranted: boolean;
|
|
190
|
+
detail: string;
|
|
191
|
+
}
|
|
192
|
+
export interface HelpersOnboardResult {
|
|
193
|
+
/** The tier this run gathered: `base`, or `gui` (base plus the GUI legs). */
|
|
194
|
+
tier: OnboardTier;
|
|
195
|
+
/**
|
|
196
|
+
* How the GUI tier came to be included: the `--gui` flag, the `ui-enabled`
|
|
197
|
+
* config key already being on, the wizard's interactive question, or not at
|
|
198
|
+
* all. Reported so the ceremony's own output can say why it did what it did.
|
|
199
|
+
*/
|
|
200
|
+
guiRequestedBy: "flag" | "config" | "wizard" | null;
|
|
201
|
+
/** True when this run turned `ui-enabled` on as part of a successful GUI tier. */
|
|
202
|
+
uiEnabledSet: boolean;
|
|
203
|
+
steps: OnboardStep[];
|
|
204
|
+
/**
|
|
205
|
+
* The legs that were going to put something on screen, surveyed prompt-free
|
|
206
|
+
* BEFORE the first one ran. Empty means the ceremony raised nothing.
|
|
207
|
+
*/
|
|
208
|
+
outstanding: OnboardLeg[];
|
|
209
|
+
/** Any leg refused. */
|
|
210
|
+
denied: boolean;
|
|
211
|
+
/** Any leg still waiting on a human. */
|
|
212
|
+
pending: boolean;
|
|
213
|
+
/** The single closing line printed under the report. */
|
|
214
|
+
closing: string;
|
|
215
|
+
}
|
|
216
|
+
/** The deputy transport the ceremony drives (a test seam — see {@link OnboardDeps}). */
|
|
217
|
+
export interface OnboardChannel {
|
|
218
|
+
hello(): DeputyHello;
|
|
219
|
+
request(fields: Record<string, unknown>, timeoutMs: number): Record<string, unknown>;
|
|
220
|
+
close(): void;
|
|
221
|
+
}
|
|
222
|
+
export interface OnboardDeps {
|
|
223
|
+
/** One line per step, as it happens. Default: stdout. */
|
|
224
|
+
progress?: (line: string) => void;
|
|
225
|
+
channel?: OnboardChannel;
|
|
226
|
+
/** Reader state, prompt-free: granted bookmark AND a database inside it. */
|
|
227
|
+
readerProbe?: () => {
|
|
228
|
+
granted: boolean;
|
|
229
|
+
locates: boolean;
|
|
230
|
+
} | null;
|
|
231
|
+
/** The reader's panel ceremony (default: {@link grantReader}). */
|
|
232
|
+
grant?: () => {
|
|
233
|
+
granted: boolean;
|
|
234
|
+
detail: string;
|
|
235
|
+
};
|
|
236
|
+
/** Best-effort deep link into System Settings. Default: `open <url>`. */
|
|
237
|
+
openUrl?: (url: string) => void;
|
|
238
|
+
sleep?: (ms: number) => void;
|
|
239
|
+
now?: () => number;
|
|
240
|
+
automationTimeoutMs?: number;
|
|
241
|
+
axTimeoutMs?: number;
|
|
242
|
+
axIntervalMs?: number;
|
|
243
|
+
/** How long to wait for the deputy's socket to appear (a just-installed helper is still coming up). */
|
|
244
|
+
deputyWaitMs?: number;
|
|
245
|
+
/**
|
|
246
|
+
* The Article V wizard. Default: built from TTY-ness (../wizard.ts). At a TTY
|
|
247
|
+
* it explains each dialog before the leg raises it and asks the tier question;
|
|
248
|
+
* off a TTY every method is inert and the ceremony behaves exactly as it did
|
|
249
|
+
* before the wizard existed.
|
|
250
|
+
*/
|
|
251
|
+
wizard?: Wizard;
|
|
252
|
+
/** Is `ui-enabled` already on? Default: the stored config. */
|
|
253
|
+
uiEnabled?: () => boolean;
|
|
254
|
+
/** Turn `ui-enabled` on after a successful GUI tier. Default: the config file. */
|
|
255
|
+
setUiEnabled?: (value: boolean) => void;
|
|
256
|
+
}
|
|
257
|
+
/** What `onboardHelpers` is being asked to gather. */
|
|
258
|
+
export interface OnboardOptions {
|
|
259
|
+
/** The configured routing mode, for the closing line. */
|
|
260
|
+
mode: HelpersMode;
|
|
261
|
+
/**
|
|
262
|
+
* Gather the GUI tier as well (`things helpers setup --gui`). When omitted,
|
|
263
|
+
* the tier is still included if `ui-enabled` is already on (a machine that
|
|
264
|
+
* has opted into GUI-driving is asking for the grants by definition), or if
|
|
265
|
+
* the wizard's interactive question is answered yes.
|
|
266
|
+
*/
|
|
267
|
+
gui?: boolean;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* The full onboarding ceremony behind `things helpers setup`: fire every
|
|
271
|
+
* consent macOS will ever ask for while a human is sitting there, then report
|
|
272
|
+
* where each one landed. Every leg is IDEMPOTENT — an already-granted leg is
|
|
273
|
+
* detected prompt-free (the deputy's own `hello` carries its TCC standing) and
|
|
274
|
+
* skipped — so a rerun on a fully onboarded machine raises nothing and reports
|
|
275
|
+
* all-green. Interactive by design: run it at the machine.
|
|
276
|
+
*
|
|
277
|
+
* Throws when the helpers are not installed or the deputy does not answer;
|
|
278
|
+
* every other outcome is reported per leg. See docs/design/helpers-onboarding.md.
|
|
279
|
+
*
|
|
280
|
+
* Runs under `withDefaultInterrupts` for its whole synchronous span, so Ctrl-C
|
|
281
|
+
* stops it at a gate AND inside the Accessibility wait (../wizard.ts, "Why a
|
|
282
|
+
* ceremony runs with the DEFAULT signal disposition"). Throws `CeremonyStopped`
|
|
283
|
+
* when the human stops at a gate.
|
|
284
|
+
*/
|
|
285
|
+
export declare function onboardHelpers(options: OnboardOptions, env?: NodeJS.ProcessEnv, deps?: OnboardDeps): HelpersOnboardResult;
|
|
286
|
+
export interface DeputyHalfStatus {
|
|
287
|
+
plistInstalled: boolean;
|
|
288
|
+
loaded: boolean;
|
|
289
|
+
running: boolean;
|
|
290
|
+
socketPath: string;
|
|
291
|
+
/**
|
|
292
|
+
* The socket file exists but no handshake came back (a dead process that
|
|
293
|
+
* left its socket behind, or one wedged mid-request). Distinct from plain
|
|
294
|
+
* "not running": the remedy is `things helpers restart`, not an install.
|
|
295
|
+
*/
|
|
296
|
+
hungSocket: boolean;
|
|
297
|
+
hello: DeputyHello | null;
|
|
298
|
+
signing: DeputySigning | null;
|
|
299
|
+
detail: string;
|
|
300
|
+
}
|
|
301
|
+
export interface ReaderHalfStatus extends DeputyHalfStatus {
|
|
302
|
+
installed: boolean;
|
|
303
|
+
granted: boolean;
|
|
304
|
+
}
|
|
305
|
+
export interface HelpersStatus {
|
|
306
|
+
/** The configured routing mode (`helpers-enabled`), not what it resolved to. */
|
|
307
|
+
mode: HelpersMode;
|
|
308
|
+
bundleInstalled: boolean;
|
|
309
|
+
/** The installed bundle's version (Info.plist), null when nothing is installed. */
|
|
310
|
+
installedVersion: string | null;
|
|
311
|
+
deputy: DeputyHalfStatus;
|
|
312
|
+
reader: ReaderHalfStatus;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Prompt-free status for both halves: launchd load state, a live handshake
|
|
316
|
+
* when each socket answers, and the installed bundle's signing facts. Works
|
|
317
|
+
* with routing disabled — inspect first, enable after.
|
|
318
|
+
*/
|
|
319
|
+
export declare function helpersStatus(mode: HelpersMode, env?: NodeJS.ProcessEnv): HelpersStatus;
|