shepherd-onboard 0.1.6 → 0.1.7
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 +11 -4
- package/bin/shepherd-onboard.js +49 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,10 +25,9 @@ The command:
|
|
|
25
25
|
- asks for name, organization, and an optional local Messages handle
|
|
26
26
|
- creates or reuses the Shepherd customer account from the WorkOS-authenticated email
|
|
27
27
|
- creates or reuses the organization, including case-insensitive and close-name matches
|
|
28
|
-
- opens Google authorization for Gmail, Docs, and Calendar consent
|
|
28
|
+
- opens Google Workspace authorization for Gmail, Drive, Docs, and Calendar consent
|
|
29
29
|
- opens Slack authorization
|
|
30
|
-
- opens the Granola desktop app
|
|
31
|
-
- directs the coding agent/user to Granola Settings -> Connectors -> API keys
|
|
30
|
+
- opens the Granola desktop app to Settings -> Connectors -> API keys
|
|
32
31
|
- collects the Granola API key after opening the Granola screen when Granola is enabled
|
|
33
32
|
- sets up local macOS Messages raw sync with a background LaunchAgent
|
|
34
33
|
- starts raw polling/backfill for connected sources
|
|
@@ -45,10 +44,18 @@ The command does not expose Railway, database, Redis, or internal service detail
|
|
|
45
44
|
--granola-api-key <key> Granola API key
|
|
46
45
|
--messages-handle <value> Messages phone number or Apple ID email
|
|
47
46
|
--messages-backfill-days Local Messages backfill window, default 30
|
|
48
|
-
--no-google Skip Google
|
|
47
|
+
--no-google Skip Google Workspace (Gmail/Drive/Docs/Calendar)
|
|
49
48
|
--no-slack Skip Slack
|
|
50
49
|
--no-granola Skip Granola
|
|
51
50
|
--no-open-granola Do not open the Granola API key screen
|
|
52
51
|
--no-messages Skip local Messages
|
|
53
52
|
--no-open Print auth URLs instead of opening the browser
|
|
54
53
|
```
|
|
54
|
+
|
|
55
|
+
## Granola API Keys
|
|
56
|
+
|
|
57
|
+
If Granola does not land on the API keys page, run:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
npx -y shepherd-onboard@latest granola-api-keys
|
|
61
|
+
```
|
package/bin/shepherd-onboard.js
CHANGED
|
@@ -32,6 +32,8 @@ async function dispatch() {
|
|
|
32
32
|
await runOnboarding();
|
|
33
33
|
} else if (command === "agent") {
|
|
34
34
|
await runAgentOnboarding();
|
|
35
|
+
} else if (command === "granola-api-keys") {
|
|
36
|
+
await openGranolaApiKeys({ noOpen: Boolean(args["no-open"]) });
|
|
35
37
|
} else if (command === "messages-agent") {
|
|
36
38
|
await runMessagesAgent();
|
|
37
39
|
} else {
|
|
@@ -80,9 +82,9 @@ async function runOnboarding() {
|
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
if (session.authUrls?.google) {
|
|
83
|
-
console.log("\nGoogle
|
|
85
|
+
console.log("\nGoogle Workspace authorization");
|
|
84
86
|
await openOrPrint(session.authUrls.google, { noOpen });
|
|
85
|
-
await waitForEnter("Complete Google authorization in the browser, then press Enter.");
|
|
87
|
+
await waitForEnter("Complete Google Workspace authorization in the browser, then press Enter.");
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
if (session.authUrls?.slack) {
|
|
@@ -489,6 +491,7 @@ Usage:
|
|
|
489
491
|
npx -y ${PACKAGE_NAME}@latest agent --name <name> --org <organization>
|
|
490
492
|
npx -y ${PACKAGE_NAME}@latest agent --continue --granola-api-key <key> --messages-handle <value>
|
|
491
493
|
npx -y ${PACKAGE_NAME}@latest agent --status
|
|
494
|
+
npx -y ${PACKAGE_NAME}@latest granola-api-keys
|
|
492
495
|
|
|
493
496
|
Agent mode is non-interactive. It prints the user prompt and exact commands a coding agent should run.
|
|
494
497
|
Always run --login first. WorkOS login/signup creates or relinks the Shepherd account before source setup.
|
|
@@ -516,6 +519,7 @@ Options:
|
|
|
516
519
|
Usage:
|
|
517
520
|
npx -y ${PACKAGE_NAME}@latest
|
|
518
521
|
npx -y ${PACKAGE_NAME}@latest agent
|
|
522
|
+
npx -y ${PACKAGE_NAME}@latest granola-api-keys
|
|
519
523
|
|
|
520
524
|
Options:
|
|
521
525
|
--email <email> Advanced: must match the WorkOS-authenticated email.
|
|
@@ -525,7 +529,7 @@ Options:
|
|
|
525
529
|
--messages-handle <value> Messages phone number or Apple ID email.
|
|
526
530
|
--messages-backfill-days <days>
|
|
527
531
|
Local Messages backfill window. Defaults to 30.
|
|
528
|
-
--no-google Skip Google
|
|
532
|
+
--no-google Skip Google Workspace (Gmail/Drive/Docs/Calendar).
|
|
529
533
|
--no-slack Skip Slack.
|
|
530
534
|
--no-granola Skip Granola.
|
|
531
535
|
--no-open-granola Do not open the Granola API key screen.
|
|
@@ -561,7 +565,7 @@ function printAgentContract() {
|
|
|
561
565
|
{
|
|
562
566
|
label: "Sources",
|
|
563
567
|
prompt: "Which sources should Shepherd connect for raw sync?",
|
|
564
|
-
options: ["Google
|
|
568
|
+
options: ["Google Workspace (Gmail/Drive/Docs/Calendar)", "Slack", "Granola", "Messages"],
|
|
565
569
|
multiSelect: true,
|
|
566
570
|
},
|
|
567
571
|
{
|
|
@@ -576,7 +580,7 @@ function printAgentContract() {
|
|
|
576
580
|
"Messages phone number or Apple ID email, if they want local Messages connected",
|
|
577
581
|
],
|
|
578
582
|
afterStartCommand: [
|
|
579
|
-
"Complete the opened Google authorization for Gmail, Docs, and Calendar.",
|
|
583
|
+
"Complete the opened Google Workspace authorization for Gmail, Drive, Docs, and Calendar.",
|
|
580
584
|
"Complete the opened Slack authorization.",
|
|
581
585
|
"Create/copy the Granola API key from the opened Granola Mac app API key screen, if they want Granola connected.",
|
|
582
586
|
],
|
|
@@ -597,7 +601,7 @@ function printAgentContract() {
|
|
|
597
601
|
],
|
|
598
602
|
statusCommand: `${command} agent --status`,
|
|
599
603
|
expectedResult: "Cloud sources start raw polling/backfill in the customer-facing Shepherd environment. Local Messages starts via a macOS LaunchAgent when run on macOS. Downstream wiki, memory, and summary compilers remain outside this onboarding flow.",
|
|
600
|
-
granolaApiKeyCommand:
|
|
604
|
+
granolaApiKeyCommand: `${command} granola-api-keys`,
|
|
601
605
|
granolaApiKeyPath: "Granola desktop app -> Settings -> Connectors -> API keys",
|
|
602
606
|
};
|
|
603
607
|
|
|
@@ -616,7 +620,7 @@ Ask with short interactive prompts, not as one pasted checklist.
|
|
|
616
620
|
|
|
617
621
|
Start with selection questions to determine intent:
|
|
618
622
|
1. Organization: Join existing org, or Create new org.
|
|
619
|
-
2. Sources: Google
|
|
623
|
+
2. Sources: Google Workspace (Gmail/Drive/Docs/Calendar), Slack, Granola, Messages. Allow multi-select if your interface supports it.
|
|
620
624
|
3. Messages, if selected: Skip Messages, or Provide handle.
|
|
621
625
|
|
|
622
626
|
Before source setup, always run:
|
|
@@ -642,16 +646,18 @@ Add skip flags for sources the user did not select:
|
|
|
642
646
|
- --no-granola
|
|
643
647
|
- --no-messages
|
|
644
648
|
|
|
645
|
-
That command creates/reuses the customer user and org, opens Google/Slack browser auth, and saves local state.
|
|
646
|
-
If
|
|
649
|
+
That command creates/reuses the customer user and org, opens Google Workspace/Slack browser auth, and saves local state.
|
|
650
|
+
If your browser automation can complete those auth screens, do it. If it cannot click through OAuth screens, leave the opened browser tabs for the user and ask them to complete Google Workspace and Slack auth.
|
|
651
|
+
|
|
652
|
+
If Granola is selected, it also opens the Granola desktop app. If your local app automation can navigate it, go to:
|
|
647
653
|
Settings -> Connectors -> API keys
|
|
648
654
|
Then have the user create/copy the API key.
|
|
649
655
|
|
|
650
656
|
If Granola did not come forward, run:
|
|
651
657
|
${payload.granolaApiKeyCommand}
|
|
652
|
-
|
|
658
|
+
That command opens Granola and tries to navigate to Settings -> Connectors -> API keys. If your tool cannot click inside Granola, leave Granola open and ask the user to go to that screen.
|
|
653
659
|
|
|
654
|
-
After Google
|
|
660
|
+
After Google Workspace and Slack browser auth is complete, and after the user has copied a Granola API key from the opened Granola screen if they want Granola, run:
|
|
655
661
|
${payload.continueCommand} --messages-handle "<phone_or_apple_id>" --granola-api-key "<granola_key>"
|
|
656
662
|
|
|
657
663
|
Omit either optional flag if that source is not being connected.
|
|
@@ -728,7 +734,7 @@ function authenticatedName(authenticated) {
|
|
|
728
734
|
|
|
729
735
|
function agentNeedsUserAction(sources, opened) {
|
|
730
736
|
const actions = [];
|
|
731
|
-
if (sources.google && opened.includes("google")) actions.push("Complete Google browser authorization for Gmail, Docs, and Calendar consent.");
|
|
737
|
+
if (sources.google && opened.includes("google")) actions.push("Complete Google Workspace browser authorization for Gmail, Drive, Docs, and Calendar consent.");
|
|
732
738
|
if (sources.slack && opened.includes("slack")) actions.push("Complete Slack browser authorization.");
|
|
733
739
|
if (sources.granola) actions.push("Create/copy a Granola API key from the Granola Mac app.");
|
|
734
740
|
if (sources.messages) actions.push("Pass the Messages phone number or Apple ID email collected before starting onboarding.");
|
|
@@ -843,7 +849,7 @@ async function openOrPrint(url, opts) {
|
|
|
843
849
|
}
|
|
844
850
|
|
|
845
851
|
async function openGranolaApiKeys(opts = {}) {
|
|
846
|
-
const deepLink = "granola://settings/
|
|
852
|
+
const deepLink = "granola://settings/integrations";
|
|
847
853
|
if (opts.noOpen) {
|
|
848
854
|
console.log("Granola API keys: open the Granola desktop app -> Settings -> Connectors -> API keys");
|
|
849
855
|
return { opened: false, target: "Granola Settings -> Connectors -> API keys" };
|
|
@@ -868,15 +874,44 @@ async function openGranolaApiKeys(opts = {}) {
|
|
|
868
874
|
if (bundleResult.error && activateByBundleResult.error && activateByNameResult.error) {
|
|
869
875
|
await execFileQuiet("open", ["-a", "Granola"], { ignoreError: true });
|
|
870
876
|
}
|
|
877
|
+
await navigateGranolaApiKeysWithAppleScript();
|
|
871
878
|
|
|
872
879
|
return {
|
|
873
880
|
opened: true,
|
|
874
881
|
target: "Granola Settings -> Connectors -> API keys",
|
|
875
882
|
attemptedDeepLink: deepLink,
|
|
876
|
-
fallback: "
|
|
883
|
+
fallback: "If local app automation cannot click inside Granola, ask the user to open Settings -> Connectors -> API keys.",
|
|
877
884
|
};
|
|
878
885
|
}
|
|
879
886
|
|
|
887
|
+
async function navigateGranolaApiKeysWithAppleScript() {
|
|
888
|
+
const script = `
|
|
889
|
+
tell application id "com.granola.app" to activate
|
|
890
|
+
delay 0.7
|
|
891
|
+
tell application "System Events"
|
|
892
|
+
if not (exists process "Granola") then return
|
|
893
|
+
tell process "Granola"
|
|
894
|
+
set frontmost to true
|
|
895
|
+
try
|
|
896
|
+
set {x, y} to position of window 1
|
|
897
|
+
set {w, h} to size of window 1
|
|
898
|
+
click at {x + w - 55, y + 665}
|
|
899
|
+
return
|
|
900
|
+
end try
|
|
901
|
+
try
|
|
902
|
+
keystroke "," using command down
|
|
903
|
+
delay 0.5
|
|
904
|
+
set {x, y} to position of window 1
|
|
905
|
+
set {w, h} to size of window 1
|
|
906
|
+
click at {x + w - 55, y + 665}
|
|
907
|
+
return
|
|
908
|
+
end try
|
|
909
|
+
end tell
|
|
910
|
+
end tell
|
|
911
|
+
`;
|
|
912
|
+
await execFileQuiet("osascript", ["-e", script], { ignoreError: true });
|
|
913
|
+
}
|
|
914
|
+
|
|
880
915
|
async function postJson(url, body, opts = {}) {
|
|
881
916
|
const res = await fetch(url, {
|
|
882
917
|
method: "POST",
|