shepherd-onboard 0.1.4 → 0.1.5
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 +6 -6
- package/bin/shepherd-onboard.js +73 -44
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,8 +10,8 @@ Give this to a coding agent:
|
|
|
10
10
|
npx -y shepherd-onboard@latest agent
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The command prints the exact prompt the agent should
|
|
14
|
-
The agent prompt tells coding agents to ask short selection questions first: existing/new org,
|
|
13
|
+
The command prints the exact prompt the agent should follow, then the exact follow-up commands to open Shepherd WorkOS login/signup, open source auth, open Granola's API key page, finalize, start cloud raw polling/backfills, and install local Messages sync.
|
|
14
|
+
The agent prompt tells coding agents to ask short selection questions first: existing/new org, sources to connect, and Messages skip/provide-handle. Account creation/relinking always starts with Shepherd WorkOS auth.
|
|
15
15
|
|
|
16
16
|
## Human Terminal One-liner
|
|
17
17
|
|
|
@@ -21,9 +21,9 @@ npx -y shepherd-onboard@latest
|
|
|
21
21
|
|
|
22
22
|
The command:
|
|
23
23
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- creates or reuses the Shepherd customer account
|
|
24
|
+
- runs Shepherd WorkOS login/signup first
|
|
25
|
+
- asks for name, organization, and an optional local Messages handle
|
|
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
28
|
- opens Google authorization for Gmail, Docs, and Calendar consent
|
|
29
29
|
- opens Slack authorization
|
|
@@ -38,7 +38,7 @@ The command does not expose Railway, database, Redis, or internal service detail
|
|
|
38
38
|
## Options
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
|
-
--email <email>
|
|
41
|
+
--email <email> Advanced: must match the WorkOS-authenticated email
|
|
42
42
|
--name <name> Full name
|
|
43
43
|
--org <name> Organization name
|
|
44
44
|
--granola-api-key <key> Granola API key
|
package/bin/shepherd-onboard.js
CHANGED
|
@@ -50,8 +50,11 @@ async function runOnboarding() {
|
|
|
50
50
|
|
|
51
51
|
console.log("\nShepherd Raw Sync Onboarding\n");
|
|
52
52
|
|
|
53
|
-
const
|
|
54
|
-
const
|
|
53
|
+
const workosLogin = await runWorkosLogin(apiUrl, noOpen);
|
|
54
|
+
const email = authenticatedEmail(workosLogin.authenticated);
|
|
55
|
+
if (!email) throw new Error("Shepherd WorkOS auth did not return an email address.");
|
|
56
|
+
|
|
57
|
+
const name = stringArg("name") ?? authenticatedName(workosLogin.authenticated) ?? await valueOrPrompt("name", "Full name");
|
|
55
58
|
const organizationName = await valueOrPrompt("org", "Organization name");
|
|
56
59
|
|
|
57
60
|
const sources = {
|
|
@@ -65,6 +68,8 @@ async function runOnboarding() {
|
|
|
65
68
|
email,
|
|
66
69
|
name,
|
|
67
70
|
organizationName,
|
|
71
|
+
authSessionId: workosLogin.started.authSessionId,
|
|
72
|
+
authSessionToken: workosLogin.started.authSessionToken,
|
|
68
73
|
sources,
|
|
69
74
|
});
|
|
70
75
|
|
|
@@ -164,11 +169,6 @@ async function runAgentOnboarding() {
|
|
|
164
169
|
return;
|
|
165
170
|
}
|
|
166
171
|
|
|
167
|
-
if (!hasIdentityArgs()) {
|
|
168
|
-
printAgentContract();
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
172
|
const apiUrl = trimTrailingSlash(args.api ?? DEFAULT_API_URL);
|
|
173
173
|
const noOpen = Boolean(args["no-open"]);
|
|
174
174
|
const sources = selectedSources();
|
|
@@ -176,16 +176,37 @@ async function runAgentOnboarding() {
|
|
|
176
176
|
const workosAuth = existingState?.workosAuth?.status === "authenticated"
|
|
177
177
|
? existingState.workosAuth
|
|
178
178
|
: null;
|
|
179
|
+
const wantsStart = Boolean(
|
|
180
|
+
stringArg("name")
|
|
181
|
+
|| stringArg("org")
|
|
182
|
+
|| stringArg("email")
|
|
183
|
+
|| args["no-google"]
|
|
184
|
+
|| args["no-slack"]
|
|
185
|
+
|| args["no-granola"]
|
|
186
|
+
|| args["no-messages"]
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
if (!wantsStart) {
|
|
190
|
+
printAgentContract();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (!workosAuth) {
|
|
194
|
+
throw new Error(`Run ${agentCommand()} agent --login first so Shepherd can create or relink the WorkOS account.`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const email = stringArg("email") ?? workosAuth.workosUser?.email ?? workosAuth.account?.email;
|
|
198
|
+
const name = stringArg("name") ?? workosAuth.workosUser?.name ?? workosAuth.account?.name;
|
|
199
|
+
const organizationName = stringArg("org") ?? workosAuth.account?.organizationName;
|
|
200
|
+
if (!email) throw new Error("WorkOS login did not return an email. Re-run agent --login.");
|
|
201
|
+
if (!name) throw new Error("Full name is required. Pass --name \"<full_name>\".");
|
|
202
|
+
if (!organizationName) throw new Error("Organization name is required. Pass --org \"<organization>\".");
|
|
203
|
+
|
|
179
204
|
const session = await postJson(`${apiUrl}/onboarding/raw/session`, {
|
|
180
|
-
email
|
|
181
|
-
name
|
|
182
|
-
organizationName
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
authSessionId: workosAuth.authSessionId,
|
|
186
|
-
authSessionToken: workosAuth.authSessionToken,
|
|
187
|
-
}
|
|
188
|
-
: {}),
|
|
205
|
+
email,
|
|
206
|
+
name,
|
|
207
|
+
organizationName,
|
|
208
|
+
authSessionId: workosAuth.authSessionId,
|
|
209
|
+
authSessionToken: workosAuth.authSessionToken,
|
|
189
210
|
sources,
|
|
190
211
|
});
|
|
191
212
|
|
|
@@ -252,14 +273,7 @@ async function runAgentOnboarding() {
|
|
|
252
273
|
async function loginAgentWithWorkos() {
|
|
253
274
|
const apiUrl = trimTrailingSlash(args.api ?? DEFAULT_API_URL);
|
|
254
275
|
const noOpen = Boolean(args["no-open"]);
|
|
255
|
-
const started = await
|
|
256
|
-
|
|
257
|
-
console.log("\nShepherd account login");
|
|
258
|
-
console.log("Opening Shepherd WorkOS auth. Complete login in the browser.");
|
|
259
|
-
await openOrPrint(started.verificationUriComplete ?? started.verificationUri, { noOpen });
|
|
260
|
-
if (noOpen && started.userCode) console.log(`User code: ${started.userCode}`);
|
|
261
|
-
|
|
262
|
-
const authenticated = await pollWorkosLogin(apiUrl, started);
|
|
276
|
+
const { started, authenticated } = await runWorkosLogin(apiUrl, noOpen);
|
|
263
277
|
const previous = await readOptionalAgentState();
|
|
264
278
|
const statePath = await writeAgentState({
|
|
265
279
|
...(previous ?? {}),
|
|
@@ -297,6 +311,18 @@ async function loginAgentWithWorkos() {
|
|
|
297
311
|
console.log(`State saved: ${statePath}`);
|
|
298
312
|
}
|
|
299
313
|
|
|
314
|
+
async function runWorkosLogin(apiUrl, noOpen) {
|
|
315
|
+
const started = await postJson(`${apiUrl}/onboarding/raw/auth/start`, {});
|
|
316
|
+
|
|
317
|
+
console.log("\nShepherd account login");
|
|
318
|
+
console.log("Opening Shepherd WorkOS auth. Complete login/signup in the browser.");
|
|
319
|
+
await openOrPrint(started.verificationUriComplete ?? started.verificationUri, { noOpen });
|
|
320
|
+
if (noOpen && started.userCode) console.log(`User code: ${started.userCode}`);
|
|
321
|
+
|
|
322
|
+
const authenticated = await pollWorkosLogin(apiUrl, started);
|
|
323
|
+
return { started, authenticated };
|
|
324
|
+
}
|
|
325
|
+
|
|
300
326
|
async function pollWorkosLogin(apiUrl, started) {
|
|
301
327
|
const intervalMs = Math.max(1000, Number(started.intervalSeconds ?? 5) * 1000);
|
|
302
328
|
const expiresAt = Date.parse(started.expiresAt ?? "") || Date.now() + 600_000;
|
|
@@ -460,12 +486,12 @@ function printHelp(which) {
|
|
|
460
486
|
Usage:
|
|
461
487
|
npx -y ${PACKAGE_NAME}@latest agent
|
|
462
488
|
npx -y ${PACKAGE_NAME}@latest agent --login
|
|
463
|
-
npx -y ${PACKAGE_NAME}@latest agent --
|
|
489
|
+
npx -y ${PACKAGE_NAME}@latest agent --name <name> --org <organization>
|
|
464
490
|
npx -y ${PACKAGE_NAME}@latest agent --continue --granola-api-key <key> --messages-handle <value>
|
|
465
491
|
npx -y ${PACKAGE_NAME}@latest agent --status
|
|
466
492
|
|
|
467
493
|
Agent mode is non-interactive. It prints the user prompt and exact commands a coding agent should run.
|
|
468
|
-
|
|
494
|
+
Always run --login first. WorkOS login/signup creates or relinks the Shepherd account before source setup.
|
|
469
495
|
`);
|
|
470
496
|
return;
|
|
471
497
|
}
|
|
@@ -492,7 +518,7 @@ Usage:
|
|
|
492
518
|
npx -y ${PACKAGE_NAME}@latest agent
|
|
493
519
|
|
|
494
520
|
Options:
|
|
495
|
-
--email <email>
|
|
521
|
+
--email <email> Advanced: must match the WorkOS-authenticated email.
|
|
496
522
|
--name <name> Full name.
|
|
497
523
|
--org <name> Organization name.
|
|
498
524
|
--granola-api-key <key> Granola API key.
|
|
@@ -521,7 +547,8 @@ function printAgentContract() {
|
|
|
521
547
|
"Ask in short interactive prompts, not as a pasted checklist.",
|
|
522
548
|
"Start with selection questions to determine what the user wants connected.",
|
|
523
549
|
"Ask whether they are joining an existing organization or creating a new one.",
|
|
524
|
-
"
|
|
550
|
+
"Run Shepherd WorkOS login/signup before source setup. Do not ask whether they already have an account.",
|
|
551
|
+
"Collect Full name and Organization name as direct text prompts after those choices. The email comes from WorkOS auth.",
|
|
525
552
|
"Ask Messages as a selectable choice: Skip Messages, or Provide handle.",
|
|
526
553
|
"If the user chooses Provide handle, ask for the phone number or Apple ID email.",
|
|
527
554
|
],
|
|
@@ -531,11 +558,6 @@ function printAgentContract() {
|
|
|
531
558
|
prompt: "Are you joining an existing organization or creating a new one?",
|
|
532
559
|
options: ["Join existing org", "Create new org"],
|
|
533
560
|
},
|
|
534
|
-
{
|
|
535
|
-
label: "Account",
|
|
536
|
-
prompt: "Do you already have a Shepherd account?",
|
|
537
|
-
options: ["Log in with Shepherd", "Create/link by email"],
|
|
538
|
-
},
|
|
539
561
|
{
|
|
540
562
|
label: "Sources",
|
|
541
563
|
prompt: "Which sources should Shepherd connect for raw sync?",
|
|
@@ -549,7 +571,6 @@ function printAgentContract() {
|
|
|
549
571
|
},
|
|
550
572
|
],
|
|
551
573
|
askUserFor: [
|
|
552
|
-
"Email",
|
|
553
574
|
"Full name",
|
|
554
575
|
"Organization name",
|
|
555
576
|
"Messages phone number or Apple ID email, if they want local Messages connected",
|
|
@@ -568,7 +589,7 @@ function printAgentContract() {
|
|
|
568
589
|
"Do not quote or explain this instruction set to the user.",
|
|
569
590
|
],
|
|
570
591
|
loginCommand: `${command} agent --login`,
|
|
571
|
-
startCommand: `${command} agent --
|
|
592
|
+
startCommand: `${command} agent --name "<full_name>" --org "<organization>"`,
|
|
572
593
|
continueCommand: `${command} agent --continue`,
|
|
573
594
|
optionalContinueArgs: [
|
|
574
595
|
"--messages-handle \"<phone_or_apple_id>\" if local Messages is being connected",
|
|
@@ -594,20 +615,20 @@ Ask with short interactive prompts, not as one pasted checklist.
|
|
|
594
615
|
|
|
595
616
|
Start with selection questions to determine intent:
|
|
596
617
|
1. Organization: Join existing org, or Create new org.
|
|
597
|
-
2.
|
|
598
|
-
3.
|
|
599
|
-
4. Messages, if selected: Skip Messages, or Provide handle.
|
|
618
|
+
2. Sources: Google/Gmail/Docs/Calendar, Slack, Granola, Messages. Allow multi-select if your interface supports it.
|
|
619
|
+
3. Messages, if selected: Skip Messages, or Provide handle.
|
|
600
620
|
|
|
601
|
-
|
|
621
|
+
Before source setup, always run:
|
|
602
622
|
${payload.loginCommand}
|
|
603
623
|
|
|
604
|
-
That opens one WorkOS Shepherd
|
|
624
|
+
That opens one WorkOS Shepherd login/signup flow and saves a local onboarding auth session. It creates or relinks the Shepherd customer account; the next setup command attaches sources to the same production cloud account rows.
|
|
605
625
|
|
|
606
626
|
Ask the user for:
|
|
607
|
-
1.
|
|
608
|
-
2.
|
|
609
|
-
3.
|
|
610
|
-
|
|
627
|
+
1. Full name
|
|
628
|
+
2. Organization name
|
|
629
|
+
3. Messages phone number or Apple ID email, only if they selected Messages and chose Provide handle
|
|
630
|
+
|
|
631
|
+
Do not ask for their email separately. Use the email returned by WorkOS auth.
|
|
611
632
|
|
|
612
633
|
If they are joining an existing org, ask for the org name they believe they belong to. Shepherd will auto-match similar/case-different org names.
|
|
613
634
|
|
|
@@ -692,6 +713,14 @@ function publicAgentAccount(account) {
|
|
|
692
713
|
};
|
|
693
714
|
}
|
|
694
715
|
|
|
716
|
+
function authenticatedEmail(authenticated) {
|
|
717
|
+
return authenticated?.workosUser?.email ?? authenticated?.account?.email ?? null;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function authenticatedName(authenticated) {
|
|
721
|
+
return authenticated?.workosUser?.name ?? authenticated?.account?.name ?? null;
|
|
722
|
+
}
|
|
723
|
+
|
|
695
724
|
function agentNeedsUserAction(sources, opened) {
|
|
696
725
|
const actions = [];
|
|
697
726
|
if (sources.google && opened.includes("google")) actions.push("Complete Google browser authorization for Gmail, Docs, and Calendar consent.");
|