@schoolai/shipyard 3.5.0-rc.20260504.0 → 3.5.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 (52) hide show
  1. package/dist/{auth-LS3NBD42.js → auth-SS7LV5XK.js} +4 -3
  2. package/dist/{chunk-GLH3V7NG.js → chunk-2J3WSIAF.js} +5 -3
  3. package/dist/{chunk-GLH3V7NG.js.map → chunk-2J3WSIAF.js.map} +1 -1
  4. package/dist/{chunk-YUG27SAR.js → chunk-2UN5AR7V.js} +2 -2
  5. package/dist/{chunk-ODCN6W33.js → chunk-3CAEALVL.js} +7 -5
  6. package/dist/{chunk-ODCN6W33.js.map → chunk-3CAEALVL.js.map} +1 -1
  7. package/dist/chunk-3MNPDCO5.js +1011 -0
  8. package/dist/chunk-3MNPDCO5.js.map +1 -0
  9. package/dist/{chunk-JQ7HCEFS.js → chunk-BNEE7ZPW.js} +8 -6
  10. package/dist/{chunk-JQ7HCEFS.js.map → chunk-BNEE7ZPW.js.map} +1 -1
  11. package/dist/{chunk-5LIPEC7P.js → chunk-GIFN3IPT.js} +4 -4
  12. package/dist/{chunk-3TB4VNFG.js → chunk-IISLTKYY.js} +2 -2
  13. package/dist/chunk-PI77CUEP.js +49 -0
  14. package/dist/chunk-PI77CUEP.js.map +1 -0
  15. package/dist/chunk-SNYEQHUK.js +64 -0
  16. package/dist/chunk-SNYEQHUK.js.map +1 -0
  17. package/dist/{chunk-XXTIKBCU.js → chunk-VBPHGPBR.js} +2 -2
  18. package/dist/{chunk-M5M6VC5F.js → chunk-VPMN47TL.js} +31 -72
  19. package/dist/chunk-VPMN47TL.js.map +1 -0
  20. package/dist/{git-repo-CNIKBYPB.js → git-repo-364VANDM.js} +5 -4
  21. package/dist/index.js +9 -8
  22. package/dist/index.js.map +1 -1
  23. package/dist/{logger-7XW3I4XN.js → logger-GQCSLSZH.js} +4 -3
  24. package/dist/{login-RHZDNC74.js → login-D6USDG5M.js} +7 -6
  25. package/dist/{logout-CUAAF5IK.js → logout-VUNCW5B2.js} +6 -5
  26. package/dist/{logout-CUAAF5IK.js.map → logout-VUNCW5B2.js.map} +1 -1
  27. package/dist/mcp-servers-FZV2P2ZO.js +16 -0
  28. package/dist/{roi-LN7MMRH7.js → roi-Y3MX5UW4.js} +4 -3
  29. package/dist/{roi-LN7MMRH7.js.map → roi-Y3MX5UW4.js.map} +1 -1
  30. package/dist/{serve-E7CHPJD4.js → serve-IVUGCBEE.js} +73 -462
  31. package/dist/{serve-E7CHPJD4.js.map → serve-IVUGCBEE.js.map} +1 -1
  32. package/dist/services/watcher-worker/worker.d.ts +49 -0
  33. package/dist/services/watcher-worker/worker.js +157 -0
  34. package/dist/services/watcher-worker/worker.js.map +1 -0
  35. package/dist/{skills-OMDIMU7D.js → skills-GPGRNV4R.js} +2 -2
  36. package/dist/start-I7ZONWK7.js +285 -0
  37. package/dist/start-I7ZONWK7.js.map +1 -0
  38. package/package.json +1 -1
  39. package/dist/chunk-M5M6VC5F.js.map +0 -1
  40. package/dist/mcp-servers-3SHS2PEJ.js +0 -15
  41. package/dist/start-HQ42GOYF.js +0 -36
  42. package/dist/start-HQ42GOYF.js.map +0 -1
  43. /package/dist/{auth-LS3NBD42.js.map → auth-SS7LV5XK.js.map} +0 -0
  44. /package/dist/{chunk-YUG27SAR.js.map → chunk-2UN5AR7V.js.map} +0 -0
  45. /package/dist/{chunk-5LIPEC7P.js.map → chunk-GIFN3IPT.js.map} +0 -0
  46. /package/dist/{chunk-3TB4VNFG.js.map → chunk-IISLTKYY.js.map} +0 -0
  47. /package/dist/{chunk-XXTIKBCU.js.map → chunk-VBPHGPBR.js.map} +0 -0
  48. /package/dist/{git-repo-CNIKBYPB.js.map → git-repo-364VANDM.js.map} +0 -0
  49. /package/dist/{logger-7XW3I4XN.js.map → logger-GQCSLSZH.js.map} +0 -0
  50. /package/dist/{login-RHZDNC74.js.map → login-D6USDG5M.js.map} +0 -0
  51. /package/dist/{mcp-servers-3SHS2PEJ.js.map → mcp-servers-FZV2P2ZO.js.map} +0 -0
  52. /package/dist/{skills-OMDIMU7D.js.map → skills-GPGRNV4R.js.map} +0 -0
@@ -5,8 +5,9 @@ import {
5
5
  loadAuthToken,
6
6
  readConfig,
7
7
  writeConfig
8
- } from "./chunk-GLH3V7NG.js";
9
- import "./chunk-M5M6VC5F.js";
8
+ } from "./chunk-2J3WSIAF.js";
9
+ import "./chunk-PI77CUEP.js";
10
+ import "./chunk-VPMN47TL.js";
10
11
  import "./chunk-2H7UOFLK.js";
11
12
  export {
12
13
  deleteConfig,
@@ -15,4 +16,4 @@ export {
15
16
  readConfig,
16
17
  writeConfig
17
18
  };
18
- //# sourceMappingURL=auth-LS3NBD42.js.map
19
+ //# sourceMappingURL=auth-SS7LV5XK.js.map
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- external_exports,
4
3
  getShipyardHome
5
- } from "./chunk-M5M6VC5F.js";
4
+ } from "./chunk-PI77CUEP.js";
5
+ import {
6
+ external_exports
7
+ } from "./chunk-VPMN47TL.js";
6
8
 
7
9
  // src/services/bootstrap/auth.ts
8
10
  import { mkdir, readFile, unlink, writeFile } from "fs/promises";
@@ -73,4 +75,4 @@ export {
73
75
  deleteConfig,
74
76
  loadAuthToken
75
77
  };
76
- //# sourceMappingURL=chunk-GLH3V7NG.js.map
78
+ //# sourceMappingURL=chunk-2J3WSIAF.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/bootstrap/auth.ts"],"sourcesContent":["import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\nimport { getShipyardHome } from '../../shared/env.js';\n\nconst ShipyardConfigSchema = z.object({\n auth: z.object({\n token: z.string(),\n userId: z.string(),\n displayName: z.string(),\n providers: z.array(z.string()),\n expiresAt: z.number(),\n signalingUrl: z.string(),\n }),\n});\n\nexport type ShipyardConfig = z.infer<typeof ShipyardConfigSchema>;\n\nexport function getConfigPath(): string {\n return join(getShipyardHome(), 'config.json');\n}\n\nexport async function readConfig(): Promise<ShipyardConfig | null> {\n try {\n const raw = await readFile(getConfigPath(), 'utf-8');\n return ShipyardConfigSchema.parse(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n\nexport async function writeConfig(config: ShipyardConfig): Promise<void> {\n await mkdir(dirname(getConfigPath()), { recursive: true, mode: 0o700 });\n await writeFile(getConfigPath(), `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n}\n\nexport async function deleteConfig(): Promise<boolean> {\n try {\n await unlink(getConfigPath());\n return true;\n } catch {\n return false;\n }\n}\n\nexport type AuthResult =\n | { status: 'ok'; token: string; userId: string; displayName: string; signalingUrl?: string }\n | { status: 'expired' }\n | { status: 'missing' };\n\nexport interface AuthEnvOverrides {\n SHIPYARD_USER_TOKEN?: string;\n SHIPYARD_USER_ID?: string;\n SHIPYARD_USER_DISPLAY_NAME?: string;\n SHIPYARD_SIGNALING_URL?: string;\n}\n\n/**\n * Load auth token from validated env (CI override) or config file.\n */\nexport async function loadAuthToken(envOverrides?: AuthEnvOverrides): Promise<AuthResult> {\n const envToken = envOverrides?.SHIPYARD_USER_TOKEN;\n if (envToken) {\n return {\n status: 'ok',\n token: envToken,\n userId: envOverrides?.SHIPYARD_USER_ID ?? '',\n displayName: envOverrides?.SHIPYARD_USER_DISPLAY_NAME ?? '',\n signalingUrl: envOverrides?.SHIPYARD_SIGNALING_URL,\n };\n }\n\n const config = await readConfig();\n if (!config?.auth?.token) return { status: 'missing' };\n\n if (config.auth.expiresAt < Date.now()) {\n return { status: 'expired' };\n }\n\n return {\n status: 'ok',\n token: config.auth.token,\n userId: config.auth.userId,\n displayName: config.auth.displayName,\n signalingUrl: config.auth.signalingUrl,\n };\n}\n"],"mappings":";;;;;;;AAAA,SAAS,OAAO,UAAU,QAAQ,iBAAiB;AACnD,SAAS,SAAS,YAAY;AAI9B,IAAM,uBAAuB,iBAAE,OAAO;AAAA,EACpC,MAAM,iBAAE,OAAO;AAAA,IACb,OAAO,iBAAE,OAAO;AAAA,IAChB,QAAQ,iBAAE,OAAO;AAAA,IACjB,aAAa,iBAAE,OAAO;AAAA,IACtB,WAAW,iBAAE,MAAM,iBAAE,OAAO,CAAC;AAAA,IAC7B,WAAW,iBAAE,OAAO;AAAA,IACpB,cAAc,iBAAE,OAAO;AAAA,EACzB,CAAC;AACH,CAAC;AAIM,SAAS,gBAAwB;AACtC,SAAO,KAAK,gBAAgB,GAAG,aAAa;AAC9C;AAEA,eAAsB,aAA6C;AACjE,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,cAAc,GAAG,OAAO;AACnD,WAAO,qBAAqB,MAAM,KAAK,MAAM,GAAG,CAAC;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YAAY,QAAuC;AACvE,QAAM,MAAM,QAAQ,cAAc,CAAC,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACtE,QAAM,UAAU,cAAc,GAAG,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAC1F;AAEA,eAAsB,eAAiC;AACrD,MAAI;AACF,UAAM,OAAO,cAAc,CAAC;AAC5B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAiBA,eAAsB,cAAc,cAAsD;AACxF,QAAM,WAAW,cAAc;AAC/B,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ,cAAc,oBAAoB;AAAA,MAC1C,aAAa,cAAc,8BAA8B;AAAA,MACzD,cAAc,cAAc;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,WAAW;AAChC,MAAI,CAAC,QAAQ,MAAM,MAAO,QAAO,EAAE,QAAQ,UAAU;AAErD,MAAI,OAAO,KAAK,YAAY,KAAK,IAAI,GAAG;AACtC,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,OAAO,OAAO,KAAK;AAAA,IACnB,QAAQ,OAAO,KAAK;AAAA,IACpB,aAAa,OAAO,KAAK;AAAA,IACzB,cAAc,OAAO,KAAK;AAAA,EAC5B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/services/bootstrap/auth.ts"],"sourcesContent":["import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\nimport { getShipyardHome } from '../../shared/env.js';\n\nconst ShipyardConfigSchema = z.object({\n auth: z.object({\n token: z.string(),\n userId: z.string(),\n displayName: z.string(),\n providers: z.array(z.string()),\n expiresAt: z.number(),\n signalingUrl: z.string(),\n }),\n});\n\nexport type ShipyardConfig = z.infer<typeof ShipyardConfigSchema>;\n\nexport function getConfigPath(): string {\n return join(getShipyardHome(), 'config.json');\n}\n\nexport async function readConfig(): Promise<ShipyardConfig | null> {\n try {\n const raw = await readFile(getConfigPath(), 'utf-8');\n return ShipyardConfigSchema.parse(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n\nexport async function writeConfig(config: ShipyardConfig): Promise<void> {\n await mkdir(dirname(getConfigPath()), { recursive: true, mode: 0o700 });\n await writeFile(getConfigPath(), `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n}\n\nexport async function deleteConfig(): Promise<boolean> {\n try {\n await unlink(getConfigPath());\n return true;\n } catch {\n return false;\n }\n}\n\nexport type AuthResult =\n | { status: 'ok'; token: string; userId: string; displayName: string; signalingUrl?: string }\n | { status: 'expired' }\n | { status: 'missing' };\n\nexport interface AuthEnvOverrides {\n SHIPYARD_USER_TOKEN?: string;\n SHIPYARD_USER_ID?: string;\n SHIPYARD_USER_DISPLAY_NAME?: string;\n SHIPYARD_SIGNALING_URL?: string;\n}\n\n/**\n * Load auth token from validated env (CI override) or config file.\n */\nexport async function loadAuthToken(envOverrides?: AuthEnvOverrides): Promise<AuthResult> {\n const envToken = envOverrides?.SHIPYARD_USER_TOKEN;\n if (envToken) {\n return {\n status: 'ok',\n token: envToken,\n userId: envOverrides?.SHIPYARD_USER_ID ?? '',\n displayName: envOverrides?.SHIPYARD_USER_DISPLAY_NAME ?? '',\n signalingUrl: envOverrides?.SHIPYARD_SIGNALING_URL,\n };\n }\n\n const config = await readConfig();\n if (!config?.auth?.token) return { status: 'missing' };\n\n if (config.auth.expiresAt < Date.now()) {\n return { status: 'expired' };\n }\n\n return {\n status: 'ok',\n token: config.auth.token,\n userId: config.auth.userId,\n displayName: config.auth.displayName,\n signalingUrl: config.auth.signalingUrl,\n };\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,OAAO,UAAU,QAAQ,iBAAiB;AACnD,SAAS,SAAS,YAAY;AAI9B,IAAM,uBAAuB,iBAAE,OAAO;AAAA,EACpC,MAAM,iBAAE,OAAO;AAAA,IACb,OAAO,iBAAE,OAAO;AAAA,IAChB,QAAQ,iBAAE,OAAO;AAAA,IACjB,aAAa,iBAAE,OAAO;AAAA,IACtB,WAAW,iBAAE,MAAM,iBAAE,OAAO,CAAC;AAAA,IAC7B,WAAW,iBAAE,OAAO;AAAA,IACpB,cAAc,iBAAE,OAAO;AAAA,EACzB,CAAC;AACH,CAAC;AAIM,SAAS,gBAAwB;AACtC,SAAO,KAAK,gBAAgB,GAAG,aAAa;AAC9C;AAEA,eAAsB,aAA6C;AACjE,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,cAAc,GAAG,OAAO;AACnD,WAAO,qBAAqB,MAAM,KAAK,MAAM,GAAG,CAAC;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YAAY,QAAuC;AACvE,QAAM,MAAM,QAAQ,cAAc,CAAC,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACtE,QAAM,UAAU,cAAc,GAAG,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAC1F;AAEA,eAAsB,eAAiC;AACrD,MAAI;AACF,UAAM,OAAO,cAAc,CAAC;AAC5B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAiBA,eAAsB,cAAc,cAAsD;AACxF,QAAM,WAAW,cAAc;AAC/B,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ,cAAc,oBAAoB;AAAA,MAC1C,aAAa,cAAc,8BAA8B;AAAA,MACzD,cAAc,cAAc;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,WAAW;AAChC,MAAI,CAAC,QAAQ,MAAM,MAAO,QAAO,EAAE,QAAQ,UAAU;AAErD,MAAI,OAAO,KAAK,YAAY,KAAK,IAAI,GAAG;AACtC,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,OAAO,OAAO,KAAK;AAAA,IACnB,QAAQ,OAAO,KAAK;AAAA,IACpB,aAAa,OAAO,KAAK;AAAA,IACzB,cAAc,OAAO,KAAK;AAAA,EAC5B;AACF;","names":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getShipyardHome
4
- } from "./chunk-M5M6VC5F.js";
4
+ } from "./chunk-PI77CUEP.js";
5
5
 
6
6
  // src/shared/logger.ts
7
7
  import { mkdirSync } from "fs";
@@ -54,4 +54,4 @@ export {
54
54
  createChildLogger,
55
55
  flushLogger
56
56
  };
57
- //# sourceMappingURL=chunk-YUG27SAR.js.map
57
+ //# sourceMappingURL=chunk-2UN5AR7V.js.map
@@ -9,17 +9,19 @@ import {
9
9
  import {
10
10
  print,
11
11
  printError
12
- } from "./chunk-3TB4VNFG.js";
12
+ } from "./chunk-IISLTKYY.js";
13
13
  import {
14
14
  getConfigPath,
15
15
  loadAuthToken,
16
16
  readConfig,
17
17
  writeConfig
18
- } from "./chunk-GLH3V7NG.js";
18
+ } from "./chunk-2J3WSIAF.js";
19
19
  import {
20
- external_exports,
21
20
  isDevMode
22
- } from "./chunk-M5M6VC5F.js";
21
+ } from "./chunk-PI77CUEP.js";
22
+ import {
23
+ external_exports
24
+ } from "./chunk-VPMN47TL.js";
23
25
 
24
26
  // src/shared/commands/login.ts
25
27
  var DEFAULT_SIGNALING_URL = "https://shipyard-session-server.jacob-191.workers.dev";
@@ -217,4 +219,4 @@ export {
217
219
  ensureAuthenticated,
218
220
  loginCommand
219
221
  };
220
- //# sourceMappingURL=chunk-ODCN6W33.js.map
222
+ //# sourceMappingURL=chunk-3CAEALVL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/commands/login.ts"],"sourcesContent":["import {\n DeviceExchangeCodeResponseSchema,\n DevicePollPendingSchema,\n DevicePollResponseSchema,\n DeviceStartResponseSchema,\n ROUTES,\n} from '@shipyard/session';\nimport { z } from 'zod';\nimport {\n getConfigPath,\n loadAuthToken,\n readConfig,\n type ShipyardConfig,\n writeConfig,\n} from '../../services/bootstrap/auth.js';\nimport { isDevMode } from '../env.js';\nimport { print, printError } from './output.js';\n\nconst DEFAULT_SIGNALING_URL = 'https://shipyard-session-server.jacob-191.workers.dev';\nconst DEFAULT_DEV_SIGNALING_URL = 'http://localhost:4444';\n\nexport function getSignalingUrl(): string {\n return (\n process.env.SHIPYARD_SIGNALING_URL ??\n (isDevMode() ? DEFAULT_DEV_SIGNALING_URL : DEFAULT_SIGNALING_URL)\n );\n}\n\nexport interface AuthConfig {\n token: string;\n userId: string;\n displayName: string;\n signalingUrl: string;\n}\n\nexport interface AuthResult extends AuthConfig {\n deviceFlowRan: boolean;\n}\n\n/**\n * Ensure the user is authenticated, running the device flow interactively if needed.\n * Returns the auth config on success, or calls process.exit(1) on failure.\n */\nexport async function ensureAuthenticated(opts: {\n signalingUrl: string;\n webCode?: string;\n}): Promise<AuthResult> {\n const existing = await loadAuthToken();\n\n if (existing.status === 'ok') {\n return {\n token: existing.token,\n userId: existing.userId,\n displayName: existing.displayName,\n signalingUrl: existing.signalingUrl ?? opts.signalingUrl,\n deviceFlowRan: false,\n };\n }\n\n if (existing.status === 'expired') {\n print(' Token expired. Starting re-authentication...\\n');\n }\n\n if (opts.webCode) {\n try {\n return await runWebCodeFlow(opts.signalingUrl, opts.webCode);\n } catch {\n print(' Web code expired or invalid. Starting standard login...\\n');\n }\n }\n\n return runDeviceFlow(opts.signalingUrl);\n}\n\nasync function runDeviceFlow(signalingUrl: string): Promise<AuthResult> {\n const startData = await startDeviceFlow(signalingUrl);\n\n print(` Open this URL in your browser:\\n`);\n print(` ${startData.verificationUri}\\n`);\n print(` Your code: ${startData.userCode}\\n`);\n print(' Waiting for authorization...');\n\n if (!process.env.SHIPYARD_NO_OPEN) {\n import('open').then(({ default: open }) => open(startData.verificationUri)).catch(() => {});\n }\n\n const interval = (startData.interval ?? 5) * 1000;\n const deadline = Date.now() + startData.expiresIn * 1000;\n\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, interval));\n\n try {\n const pollRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_POLL}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deviceCode: startData.deviceCode }),\n });\n\n if (pollRes.ok) {\n const result = await handleSuccessfulPoll(pollRes, signalingUrl);\n return result;\n }\n\n await handlePollError(pollRes, interval);\n } catch (err: unknown) {\n printError('Device flow poll failed', err instanceof Error ? err : undefined);\n }\n }\n\n printError('\\n Authorization timed out. Run `shipyard login` again.');\n process.exit(1);\n}\n\nasync function runWebCodeFlow(signalingUrl: string, userCode: string): Promise<AuthResult> {\n print(' Authenticating via web app code...\\n');\n\n let deviceCode: string | undefined;\n for (let attempt = 0; attempt < 3; attempt++) {\n if (attempt > 0) await new Promise((r) => setTimeout(r, 1000));\n\n const exchangeRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_EXCHANGE_CODE}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ userCode }),\n });\n\n if (exchangeRes.ok) {\n const parsed = DeviceExchangeCodeResponseSchema.parse(await exchangeRes.json());\n deviceCode = parsed.deviceCode;\n break;\n }\n\n if (attempt === 2) {\n throw new Error(`Exchange failed after 3 attempts: ${exchangeRes.status}`);\n }\n }\n\n if (!deviceCode) throw new Error('Exchange failed: no device code');\n\n const pollRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_POLL}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deviceCode }),\n });\n\n if (!pollRes.ok) {\n throw new Error(`Poll failed: ${pollRes.status}`);\n }\n\n const result = await handleSuccessfulPoll(pollRes, signalingUrl);\n print(' Authenticated via web app\\n');\n return result;\n}\n\nexport async function loginCommand(options: { check?: boolean }): Promise<void> {\n if (options.check) {\n return checkLogin();\n }\n\n const signalingUrl = getSignalingUrl();\n await runDeviceFlow(signalingUrl);\n}\n\nasync function startDeviceFlow(signalingUrl: string) {\n print('Starting device authorization...\\n');\n\n let startRes: Response;\n try {\n startRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_START}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n });\n } catch (err) {\n printError(\n `Could not reach signaling server at ${signalingUrl}`,\n err instanceof Error ? err : undefined\n );\n printError('Check your internet connection or set SHIPYARD_SIGNALING_URL.');\n process.exit(1);\n }\n\n if (!startRes.ok) {\n printError(`Failed to start device flow: ${startRes.status}`);\n process.exit(1);\n }\n\n return DeviceStartResponseSchema.parse(await startRes.json());\n}\n\nfunction extractTokenExpiry(token: string): number {\n const fallback = Date.now() + 30 * 24 * 60 * 60 * 1000;\n try {\n const payloadB64 = token.split('.')[1];\n if (!payloadB64) return fallback;\n const payload: unknown = JSON.parse(Buffer.from(payloadB64, 'base64url').toString());\n const exp = z.object({ exp: z.number() }).safeParse(payload);\n return exp.success ? exp.data.exp * 1000 : fallback;\n } catch {\n return fallback;\n }\n}\n\nasync function handleSuccessfulPoll(pollRes: Response, signalingUrl: string): Promise<AuthResult> {\n const pollData = DevicePollResponseSchema.parse(await pollRes.json());\n const expiresAt = extractTokenExpiry(pollData.token);\n\n const config: ShipyardConfig = {\n auth: {\n token: pollData.token,\n userId: pollData.user.id,\n displayName: pollData.user.displayName,\n providers: pollData.user.providers,\n expiresAt,\n signalingUrl,\n },\n };\n\n await writeConfig(config);\n\n print(`\\n Logged in as ${pollData.user.displayName} (${pollData.user.providers.join(', ')})`);\n print(` Token saved to ${getConfigPath()}`);\n\n return {\n token: pollData.token,\n userId: pollData.user.id,\n displayName: pollData.user.displayName,\n signalingUrl,\n deviceFlowRan: true,\n };\n}\n\nasync function handlePollError(pollRes: Response, interval: number): Promise<void> {\n try {\n const errorData = DevicePollPendingSchema.parse(await pollRes.json());\n\n if (errorData.error === 'expired_token') {\n printError('\\n Authorization expired. Run `shipyard login` again.');\n process.exit(1);\n }\n\n if (errorData.error === 'slow_down') {\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n } catch (err: unknown) {\n printError('Failed to parse poll error response', err instanceof Error ? err : undefined);\n }\n}\n\nasync function checkLogin(): Promise<void> {\n const config = await readConfig();\n\n if (!config?.auth?.token) {\n print('Not logged in. Run `shipyard login` to authenticate.');\n process.exit(1);\n }\n\n if (config.auth.expiresAt < Date.now()) {\n print('Token expired. Run `shipyard login` to re-authenticate.');\n process.exit(1);\n }\n\n const daysLeft = Math.ceil((config.auth.expiresAt - Date.now()) / (24 * 60 * 60 * 1000));\n print(`Logged in as ${config.auth.displayName} (${config.auth.providers.join(', ')})`);\n print(`Token expires in ${daysLeft} days`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAkBA,IAAM,wBAAwB;AAC9B,IAAM,4BAA4B;AAE3B,SAAS,kBAA0B;AACxC,SACE,QAAQ,IAAI,2BACX,UAAU,IAAI,4BAA4B;AAE/C;AAiBA,eAAsB,oBAAoB,MAGlB;AACtB,QAAM,WAAW,MAAM,cAAc;AAErC,MAAI,SAAS,WAAW,MAAM;AAC5B,WAAO;AAAA,MACL,OAAO,SAAS;AAAA,MAChB,QAAQ,SAAS;AAAA,MACjB,aAAa,SAAS;AAAA,MACtB,cAAc,SAAS,gBAAgB,KAAK;AAAA,MAC5C,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,WAAW;AACjC,UAAM,kDAAkD;AAAA,EAC1D;AAEA,MAAI,KAAK,SAAS;AAChB,QAAI;AACF,aAAO,MAAM,eAAe,KAAK,cAAc,KAAK,OAAO;AAAA,IAC7D,QAAQ;AACN,YAAM,6DAA6D;AAAA,IACrE;AAAA,EACF;AAEA,SAAO,cAAc,KAAK,YAAY;AACxC;AAEA,eAAe,cAAc,cAA2C;AACtE,QAAM,YAAY,MAAM,gBAAgB,YAAY;AAEpD,QAAM;AAAA,CAAoC;AAC1C,QAAM,OAAO,UAAU,eAAe;AAAA,CAAI;AAC1C,QAAM,gBAAgB,UAAU,QAAQ;AAAA,CAAI;AAC5C,QAAM,gCAAgC;AAEtC,MAAI,CAAC,QAAQ,IAAI,kBAAkB;AACjC,WAAO,oBAAM,EAAE,KAAK,CAAC,EAAE,SAAS,KAAK,MAAM,KAAK,UAAU,eAAe,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC5F;AAEA,QAAM,YAAY,UAAU,YAAY,KAAK;AAC7C,QAAM,WAAW,KAAK,IAAI,IAAI,UAAU,YAAY;AAEpD,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,QAAQ,CAAC;AAE5D,QAAI;AACF,YAAM,UAAU,MAAM,MAAM,GAAG,YAAY,GAAG,OAAO,gBAAgB,IAAI;AAAA,QACvE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,YAAY,UAAU,WAAW,CAAC;AAAA,MAC3D,CAAC;AAED,UAAI,QAAQ,IAAI;AACd,cAAM,SAAS,MAAM,qBAAqB,SAAS,YAAY;AAC/D,eAAO;AAAA,MACT;AAEA,YAAM,gBAAgB,SAAS,QAAQ;AAAA,IACzC,SAAS,KAAc;AACrB,iBAAW,2BAA2B,eAAe,QAAQ,MAAM,MAAS;AAAA,IAC9E;AAAA,EACF;AAEA,aAAW,0DAA0D;AACrE,UAAQ,KAAK,CAAC;AAChB;AAEA,eAAe,eAAe,cAAsB,UAAuC;AACzF,QAAM,wCAAwC;AAE9C,MAAI;AACJ,WAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,QAAI,UAAU,EAAG,OAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAI,CAAC;AAE7D,UAAM,cAAc,MAAM,MAAM,GAAG,YAAY,GAAG,OAAO,yBAAyB,IAAI;AAAA,MACpF,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,CAAC;AAAA,IACnC,CAAC;AAED,QAAI,YAAY,IAAI;AAClB,YAAM,SAAS,iCAAiC,MAAM,MAAM,YAAY,KAAK,CAAC;AAC9E,mBAAa,OAAO;AACpB;AAAA,IACF;AAEA,QAAI,YAAY,GAAG;AACjB,YAAM,IAAI,MAAM,qCAAqC,YAAY,MAAM,EAAE;AAAA,IAC3E;AAAA,EACF;AAEA,MAAI,CAAC,WAAY,OAAM,IAAI,MAAM,iCAAiC;AAElE,QAAM,UAAU,MAAM,MAAM,GAAG,YAAY,GAAG,OAAO,gBAAgB,IAAI;AAAA,IACvE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,EAAE,WAAW,CAAC;AAAA,EACrC,CAAC;AAED,MAAI,CAAC,QAAQ,IAAI;AACf,UAAM,IAAI,MAAM,gBAAgB,QAAQ,MAAM,EAAE;AAAA,EAClD;AAEA,QAAM,SAAS,MAAM,qBAAqB,SAAS,YAAY;AAC/D,QAAM,+BAA+B;AACrC,SAAO;AACT;AAEA,eAAsB,aAAa,SAA6C;AAC9E,MAAI,QAAQ,OAAO;AACjB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,eAAe,gBAAgB;AACrC,QAAM,cAAc,YAAY;AAClC;AAEA,eAAe,gBAAgB,cAAsB;AACnD,QAAM,oCAAoC;AAE1C,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,GAAG,YAAY,GAAG,OAAO,iBAAiB,IAAI;AAAA,MACnE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAChD,CAAC;AAAA,EACH,SAAS,KAAK;AACZ;AAAA,MACE,uCAAuC,YAAY;AAAA,MACnD,eAAe,QAAQ,MAAM;AAAA,IAC/B;AACA,eAAW,+DAA+D;AAC1E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,eAAW,gCAAgC,SAAS,MAAM,EAAE;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO,0BAA0B,MAAM,MAAM,SAAS,KAAK,CAAC;AAC9D;AAEA,SAAS,mBAAmB,OAAuB;AACjD,QAAM,WAAW,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK;AAClD,MAAI;AACF,UAAM,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC;AACrC,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,UAAmB,KAAK,MAAM,OAAO,KAAK,YAAY,WAAW,EAAE,SAAS,CAAC;AACnF,UAAM,MAAM,iBAAE,OAAO,EAAE,KAAK,iBAAE,OAAO,EAAE,CAAC,EAAE,UAAU,OAAO;AAC3D,WAAO,IAAI,UAAU,IAAI,KAAK,MAAM,MAAO;AAAA,EAC7C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,qBAAqB,SAAmB,cAA2C;AAChG,QAAM,WAAW,yBAAyB,MAAM,MAAM,QAAQ,KAAK,CAAC;AACpE,QAAM,YAAY,mBAAmB,SAAS,KAAK;AAEnD,QAAM,SAAyB;AAAA,IAC7B,MAAM;AAAA,MACJ,OAAO,SAAS;AAAA,MAChB,QAAQ,SAAS,KAAK;AAAA,MACtB,aAAa,SAAS,KAAK;AAAA,MAC3B,WAAW,SAAS,KAAK;AAAA,MACzB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,MAAM;AAExB,QAAM;AAAA,iBAAoB,SAAS,KAAK,WAAW,KAAK,SAAS,KAAK,UAAU,KAAK,IAAI,CAAC,GAAG;AAC7F,QAAM,oBAAoB,cAAc,CAAC,EAAE;AAE3C,SAAO;AAAA,IACL,OAAO,SAAS;AAAA,IAChB,QAAQ,SAAS,KAAK;AAAA,IACtB,aAAa,SAAS,KAAK;AAAA,IAC3B;AAAA,IACA,eAAe;AAAA,EACjB;AACF;AAEA,eAAe,gBAAgB,SAAmB,UAAiC;AACjF,MAAI;AACF,UAAM,YAAY,wBAAwB,MAAM,MAAM,QAAQ,KAAK,CAAC;AAEpE,QAAI,UAAU,UAAU,iBAAiB;AACvC,iBAAW,wDAAwD;AACnE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,UAAU,UAAU,aAAa;AACnC,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,QAAQ,CAAC;AAAA,IAC9D;AAAA,EACF,SAAS,KAAc;AACrB,eAAW,uCAAuC,eAAe,QAAQ,MAAM,MAAS;AAAA,EAC1F;AACF;AAEA,eAAe,aAA4B;AACzC,QAAM,SAAS,MAAM,WAAW;AAEhC,MAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,UAAM,sDAAsD;AAC5D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,OAAO,KAAK,YAAY,KAAK,IAAI,GAAG;AACtC,UAAM,yDAAyD;AAC/D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,KAAK,MAAM,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,KAAK,KAAK,KAAK,IAAK;AACvF,QAAM,gBAAgB,OAAO,KAAK,WAAW,KAAK,OAAO,KAAK,UAAU,KAAK,IAAI,CAAC,GAAG;AACrF,QAAM,oBAAoB,QAAQ,OAAO;AAC3C;","names":[]}
1
+ {"version":3,"sources":["../src/shared/commands/login.ts"],"sourcesContent":["import {\n DeviceExchangeCodeResponseSchema,\n DevicePollPendingSchema,\n DevicePollResponseSchema,\n DeviceStartResponseSchema,\n ROUTES,\n} from '@shipyard/session';\nimport { z } from 'zod';\nimport {\n getConfigPath,\n loadAuthToken,\n readConfig,\n type ShipyardConfig,\n writeConfig,\n} from '../../services/bootstrap/auth.js';\nimport { isDevMode } from '../env.js';\nimport { print, printError } from './output.js';\n\nconst DEFAULT_SIGNALING_URL = 'https://shipyard-session-server.jacob-191.workers.dev';\nconst DEFAULT_DEV_SIGNALING_URL = 'http://localhost:4444';\n\nexport function getSignalingUrl(): string {\n return (\n process.env.SHIPYARD_SIGNALING_URL ??\n (isDevMode() ? DEFAULT_DEV_SIGNALING_URL : DEFAULT_SIGNALING_URL)\n );\n}\n\nexport interface AuthConfig {\n token: string;\n userId: string;\n displayName: string;\n signalingUrl: string;\n}\n\nexport interface AuthResult extends AuthConfig {\n deviceFlowRan: boolean;\n}\n\n/**\n * Ensure the user is authenticated, running the device flow interactively if needed.\n * Returns the auth config on success, or calls process.exit(1) on failure.\n */\nexport async function ensureAuthenticated(opts: {\n signalingUrl: string;\n webCode?: string;\n}): Promise<AuthResult> {\n const existing = await loadAuthToken();\n\n if (existing.status === 'ok') {\n return {\n token: existing.token,\n userId: existing.userId,\n displayName: existing.displayName,\n signalingUrl: existing.signalingUrl ?? opts.signalingUrl,\n deviceFlowRan: false,\n };\n }\n\n if (existing.status === 'expired') {\n print(' Token expired. Starting re-authentication...\\n');\n }\n\n if (opts.webCode) {\n try {\n return await runWebCodeFlow(opts.signalingUrl, opts.webCode);\n } catch {\n print(' Web code expired or invalid. Starting standard login...\\n');\n }\n }\n\n return runDeviceFlow(opts.signalingUrl);\n}\n\nasync function runDeviceFlow(signalingUrl: string): Promise<AuthResult> {\n const startData = await startDeviceFlow(signalingUrl);\n\n print(` Open this URL in your browser:\\n`);\n print(` ${startData.verificationUri}\\n`);\n print(` Your code: ${startData.userCode}\\n`);\n print(' Waiting for authorization...');\n\n if (!process.env.SHIPYARD_NO_OPEN) {\n import('open').then(({ default: open }) => open(startData.verificationUri)).catch(() => {});\n }\n\n const interval = (startData.interval ?? 5) * 1000;\n const deadline = Date.now() + startData.expiresIn * 1000;\n\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, interval));\n\n try {\n const pollRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_POLL}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deviceCode: startData.deviceCode }),\n });\n\n if (pollRes.ok) {\n const result = await handleSuccessfulPoll(pollRes, signalingUrl);\n return result;\n }\n\n await handlePollError(pollRes, interval);\n } catch (err: unknown) {\n printError('Device flow poll failed', err instanceof Error ? err : undefined);\n }\n }\n\n printError('\\n Authorization timed out. Run `shipyard login` again.');\n process.exit(1);\n}\n\nasync function runWebCodeFlow(signalingUrl: string, userCode: string): Promise<AuthResult> {\n print(' Authenticating via web app code...\\n');\n\n let deviceCode: string | undefined;\n for (let attempt = 0; attempt < 3; attempt++) {\n if (attempt > 0) await new Promise((r) => setTimeout(r, 1000));\n\n const exchangeRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_EXCHANGE_CODE}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ userCode }),\n });\n\n if (exchangeRes.ok) {\n const parsed = DeviceExchangeCodeResponseSchema.parse(await exchangeRes.json());\n deviceCode = parsed.deviceCode;\n break;\n }\n\n if (attempt === 2) {\n throw new Error(`Exchange failed after 3 attempts: ${exchangeRes.status}`);\n }\n }\n\n if (!deviceCode) throw new Error('Exchange failed: no device code');\n\n const pollRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_POLL}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ deviceCode }),\n });\n\n if (!pollRes.ok) {\n throw new Error(`Poll failed: ${pollRes.status}`);\n }\n\n const result = await handleSuccessfulPoll(pollRes, signalingUrl);\n print(' Authenticated via web app\\n');\n return result;\n}\n\nexport async function loginCommand(options: { check?: boolean }): Promise<void> {\n if (options.check) {\n return checkLogin();\n }\n\n const signalingUrl = getSignalingUrl();\n await runDeviceFlow(signalingUrl);\n}\n\nasync function startDeviceFlow(signalingUrl: string) {\n print('Starting device authorization...\\n');\n\n let startRes: Response;\n try {\n startRes = await fetch(`${signalingUrl}${ROUTES.AUTH_DEVICE_START}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n });\n } catch (err) {\n printError(\n `Could not reach signaling server at ${signalingUrl}`,\n err instanceof Error ? err : undefined\n );\n printError('Check your internet connection or set SHIPYARD_SIGNALING_URL.');\n process.exit(1);\n }\n\n if (!startRes.ok) {\n printError(`Failed to start device flow: ${startRes.status}`);\n process.exit(1);\n }\n\n return DeviceStartResponseSchema.parse(await startRes.json());\n}\n\nfunction extractTokenExpiry(token: string): number {\n const fallback = Date.now() + 30 * 24 * 60 * 60 * 1000;\n try {\n const payloadB64 = token.split('.')[1];\n if (!payloadB64) return fallback;\n const payload: unknown = JSON.parse(Buffer.from(payloadB64, 'base64url').toString());\n const exp = z.object({ exp: z.number() }).safeParse(payload);\n return exp.success ? exp.data.exp * 1000 : fallback;\n } catch {\n return fallback;\n }\n}\n\nasync function handleSuccessfulPoll(pollRes: Response, signalingUrl: string): Promise<AuthResult> {\n const pollData = DevicePollResponseSchema.parse(await pollRes.json());\n const expiresAt = extractTokenExpiry(pollData.token);\n\n const config: ShipyardConfig = {\n auth: {\n token: pollData.token,\n userId: pollData.user.id,\n displayName: pollData.user.displayName,\n providers: pollData.user.providers,\n expiresAt,\n signalingUrl,\n },\n };\n\n await writeConfig(config);\n\n print(`\\n Logged in as ${pollData.user.displayName} (${pollData.user.providers.join(', ')})`);\n print(` Token saved to ${getConfigPath()}`);\n\n return {\n token: pollData.token,\n userId: pollData.user.id,\n displayName: pollData.user.displayName,\n signalingUrl,\n deviceFlowRan: true,\n };\n}\n\nasync function handlePollError(pollRes: Response, interval: number): Promise<void> {\n try {\n const errorData = DevicePollPendingSchema.parse(await pollRes.json());\n\n if (errorData.error === 'expired_token') {\n printError('\\n Authorization expired. Run `shipyard login` again.');\n process.exit(1);\n }\n\n if (errorData.error === 'slow_down') {\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n } catch (err: unknown) {\n printError('Failed to parse poll error response', err instanceof Error ? err : undefined);\n }\n}\n\nasync function checkLogin(): Promise<void> {\n const config = await readConfig();\n\n if (!config?.auth?.token) {\n print('Not logged in. Run `shipyard login` to authenticate.');\n process.exit(1);\n }\n\n if (config.auth.expiresAt < Date.now()) {\n print('Token expired. Run `shipyard login` to re-authenticate.');\n process.exit(1);\n }\n\n const daysLeft = Math.ceil((config.auth.expiresAt - Date.now()) / (24 * 60 * 60 * 1000));\n print(`Logged in as ${config.auth.displayName} (${config.auth.providers.join(', ')})`);\n print(`Token expires in ${daysLeft} days`);\n}\n"],"mappings":"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","names":[]}