gooseworks 0.4.4 → 0.5.0-dev.11.ed7fa068

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 (120) hide show
  1. package/README.md +42 -11
  2. package/dist/agents/staging.d.ts +38 -0
  3. package/dist/agents/staging.d.ts.map +1 -0
  4. package/dist/agents/staging.js +309 -0
  5. package/dist/agents/staging.js.map +1 -0
  6. package/dist/auth/credentials.d.ts +1 -0
  7. package/dist/auth/credentials.d.ts.map +1 -1
  8. package/dist/auth/credentials.js +26 -8
  9. package/dist/auth/credentials.js.map +1 -1
  10. package/dist/auth/device-flow.d.ts +79 -0
  11. package/dist/auth/device-flow.d.ts.map +1 -0
  12. package/dist/auth/device-flow.js +411 -0
  13. package/dist/auth/device-flow.js.map +1 -0
  14. package/dist/auth/login-mode.d.ts +25 -0
  15. package/dist/auth/login-mode.d.ts.map +1 -0
  16. package/dist/auth/login-mode.js +87 -0
  17. package/dist/auth/login-mode.js.map +1 -0
  18. package/dist/auth/oauth-server.d.ts +2 -2
  19. package/dist/auth/oauth-server.d.ts.map +1 -1
  20. package/dist/auth/oauth-server.js +28 -5
  21. package/dist/auth/oauth-server.js.map +1 -1
  22. package/dist/auth/paste-login.d.ts +27 -0
  23. package/dist/auth/paste-login.d.ts.map +1 -0
  24. package/dist/auth/paste-login.js +203 -0
  25. package/dist/auth/paste-login.js.map +1 -0
  26. package/dist/commands/doctor.d.ts.map +1 -1
  27. package/dist/commands/doctor.js +17 -8
  28. package/dist/commands/doctor.js.map +1 -1
  29. package/dist/commands/formats.js +2 -2
  30. package/dist/commands/formats.js.map +1 -1
  31. package/dist/commands/graphics/publish-flow.js +1 -1
  32. package/dist/commands/graphics/publish-flow.js.map +1 -1
  33. package/dist/commands/install.d.ts.map +1 -1
  34. package/dist/commands/install.js +101 -34
  35. package/dist/commands/install.js.map +1 -1
  36. package/dist/commands/launch.d.ts +3 -0
  37. package/dist/commands/launch.d.ts.map +1 -0
  38. package/dist/commands/launch.js +35 -0
  39. package/dist/commands/launch.js.map +1 -0
  40. package/dist/commands/login.d.ts +21 -1
  41. package/dist/commands/login.d.ts.map +1 -1
  42. package/dist/commands/login.js +106 -29
  43. package/dist/commands/login.js.map +1 -1
  44. package/dist/commands/logout.d.ts.map +1 -1
  45. package/dist/commands/logout.js +7 -1
  46. package/dist/commands/logout.js.map +1 -1
  47. package/dist/commands/skills.d.ts +16 -0
  48. package/dist/commands/skills.d.ts.map +1 -1
  49. package/dist/commands/skills.js +52 -1
  50. package/dist/commands/skills.js.map +1 -1
  51. package/dist/commands/styles.js +2 -2
  52. package/dist/commands/styles.js.map +1 -1
  53. package/dist/commands/tool.d.ts +17 -0
  54. package/dist/commands/tool.d.ts.map +1 -0
  55. package/dist/commands/tool.js +239 -0
  56. package/dist/commands/tool.js.map +1 -0
  57. package/dist/commands/update.d.ts.map +1 -1
  58. package/dist/commands/update.js +20 -0
  59. package/dist/commands/update.js.map +1 -1
  60. package/dist/commands/video-local.d.ts.map +1 -1
  61. package/dist/commands/video-local.js +2 -2
  62. package/dist/commands/video-local.js.map +1 -1
  63. package/dist/config.d.ts.map +1 -1
  64. package/dist/config.js +14 -3
  65. package/dist/config.js.map +1 -1
  66. package/dist/environment.d.ts +9 -0
  67. package/dist/environment.d.ts.map +1 -0
  68. package/dist/environment.js +105 -0
  69. package/dist/environment.js.map +1 -0
  70. package/dist/index.js +12 -45
  71. package/dist/index.js.map +1 -1
  72. package/dist/lib/graphics-cache.d.ts.map +1 -1
  73. package/dist/lib/graphics-cache.js +2 -2
  74. package/dist/lib/graphics-cache.js.map +1 -1
  75. package/dist/lib/mcp-client.d.ts +53 -0
  76. package/dist/lib/mcp-client.d.ts.map +1 -0
  77. package/dist/lib/mcp-client.js +196 -0
  78. package/dist/lib/mcp-client.js.map +1 -0
  79. package/dist/program.d.ts +2 -0
  80. package/dist/program.d.ts.map +1 -0
  81. package/dist/program.js +56 -0
  82. package/dist/program.js.map +1 -0
  83. package/dist/skills/custom-video-skill.d.ts +1 -1
  84. package/dist/skills/custom-video-skill.d.ts.map +1 -1
  85. package/dist/skills/custom-video-skill.js +1 -1
  86. package/dist/skills/custom-video-skill.js.map +1 -1
  87. package/dist/skills/installer.d.ts.map +1 -1
  88. package/dist/skills/installer.js +42 -24
  89. package/dist/skills/installer.js.map +1 -1
  90. package/dist/skills/master-skill.d.ts +12 -9
  91. package/dist/skills/master-skill.d.ts.map +1 -1
  92. package/dist/skills/master-skill.js +835 -372
  93. package/dist/skills/master-skill.js.map +1 -1
  94. package/dist/skills/releases.d.ts +1 -1
  95. package/dist/skills/releases.d.ts.map +1 -1
  96. package/dist/skills/releases.js +8 -5
  97. package/dist/skills/releases.js.map +1 -1
  98. package/dist/skills/routes.js +8 -8
  99. package/dist/skills/routes.js.map +1 -1
  100. package/dist/skills/staging-content.d.ts +3 -0
  101. package/dist/skills/staging-content.d.ts.map +1 -0
  102. package/dist/skills/staging-content.js +12 -0
  103. package/dist/skills/staging-content.js.map +1 -0
  104. package/dist/utils/http.d.ts +7 -1
  105. package/dist/utils/http.d.ts.map +1 -1
  106. package/dist/utils/http.js +5 -1
  107. package/dist/utils/http.js.map +1 -1
  108. package/package.json +12 -4
  109. package/skills/goose-ads/SKILL.md +386 -224
  110. package/skills/goose-product-photos/SKILL.md +107 -58
  111. package/skills/goose-video/SKILL.md +278 -36
  112. package/skills/goose-video-local/SKILL.md +239 -31
  113. package/skills/gooseworks/SKILL.md +133 -26
  114. package/skills/make-custom-video/SKILL.md +255 -11
  115. package/skills/manifest.json +7 -7
  116. package/skills/routes.json +8 -8
  117. package/dist/skills/fetcher.d.ts +0 -18
  118. package/dist/skills/fetcher.d.ts.map +0 -1
  119. package/dist/skills/fetcher.js +0 -118
  120. package/dist/skills/fetcher.js.map +0 -1
@@ -0,0 +1,79 @@
1
+ import type { OAuthResult } from './oauth-server';
2
+ export interface PendingDeviceLogin {
3
+ device_code: string;
4
+ user_code: string;
5
+ link: string;
6
+ api_base: string;
7
+ /** ISO timestamp. */
8
+ expires_at: string;
9
+ /** Seconds between polls. */
10
+ interval: number;
11
+ }
12
+ export type Sleep = (ms: number, signal?: AbortSignal) => Promise<void>;
13
+ export interface DeviceWaitDeps {
14
+ sleep?: Sleep;
15
+ now?: () => number;
16
+ }
17
+ export type DeviceFlowOutcome = {
18
+ status: 'pending';
19
+ pending: PendingDeviceLogin;
20
+ } | {
21
+ status: 'done';
22
+ result: OAuthResult;
23
+ };
24
+ /** The server predates device sign-in (`/api/cli/device/start` returned 404). */
25
+ export declare class DeviceFlowUnavailableError extends Error {
26
+ constructor();
27
+ }
28
+ /** Ctrl-C / SIGTERM while waiting. The pending request is kept so a rerun resumes. */
29
+ export declare class DeviceLoginStoppedError extends Error {
30
+ constructor();
31
+ }
32
+ export declare const EXPIRED_MESSAGE = "This sign-in code expired. Run the command again for a new link.";
33
+ export declare const DENIED_MESSAGE = "Sign-in was canceled in the browser.";
34
+ export declare const APPROVAL_GRACE_MS: number;
35
+ /**
36
+ * The saved device sign-in for `apiBase`, or null when the file is missing,
37
+ * broken, expired, or belongs to another API base.
38
+ */
39
+ export declare function readPendingDeviceLogin(apiBase: string, now?: () => number): PendingDeviceLogin | null;
40
+ export declare function clearPendingDeviceLogin(): void;
41
+ /**
42
+ * The link the user opens. Built from the CLI's own FRONTEND_URL (the same
43
+ * source `/cli/auth` uses) so local/staging overrides keep working.
44
+ */
45
+ export declare function deviceLink(userCode: string, ref?: string): string;
46
+ /**
47
+ * The link to print for a new code. An explicit GOOSEWORKS_FRONTEND_URL (local
48
+ * testing) wins. Otherwise the server's own `verification_url_complete`: it
49
+ * knows which Growth app serves /link in its environment (make.gooseworks.ai
50
+ * in production, ads-staging.gooseworks.ai on staging), which the CLI's
51
+ * FRONTEND_URL does not (staging's points at the old GTM app). It is used only
52
+ * when it is an https GooseWorks address, or a local one for a local API;
53
+ * anything else falls back to FRONTEND_URL.
54
+ */
55
+ export declare function chooseDeviceLink(serverLink: unknown, userCode: string, apiBase: string, ref?: string, env?: NodeJS.ProcessEnv): string;
56
+ export declare function startDeviceLogin(apiBase: string, ref?: string, now?: () => number, sleep?: Sleep): Promise<PendingDeviceLogin>;
57
+ /** Prints the link and code. Never opens a browser. */
58
+ export declare function printDeviceInstructions(pending: PendingDeviceLogin, opts?: {
59
+ resumed?: boolean;
60
+ now?: () => number;
61
+ }): void;
62
+ /**
63
+ * Polls until the user approves, denies, or the code expires. On success the
64
+ * key is saved like a browser sign-in and the pending file is removed. The
65
+ * server decides expiry; the local cut-off (expiry plus the approval grace)
66
+ * only stops a server that never answers.
67
+ */
68
+ export declare function waitForDeviceLogin(apiBase: string, pending: PendingDeviceLogin, deps?: DeviceWaitDeps): Promise<OAuthResult>;
69
+ /**
70
+ * Resume a saved request for this API base, or start a new one; print the
71
+ * link; then either return at once (`wait: false`) or wait for approval.
72
+ * Resuming with `wait: false` asks the server first, so it never re-prints a
73
+ * code that was already approved, canceled or used.
74
+ */
75
+ export declare function runDeviceFlow(apiBase: string, opts?: {
76
+ ref?: string;
77
+ wait?: boolean;
78
+ } & DeviceWaitDeps): Promise<DeviceFlowOutcome>;
79
+ //# sourceMappingURL=device-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,KAAK,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExE,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE5C,iFAAiF;AACjF,qBAAa,0BAA2B,SAAQ,KAAK;;CAKpD;AAED,sFAAsF;AACtF,qBAAa,uBAAwB,SAAQ,KAAK;;CAKjD;AAED,eAAO,MAAM,eAAe,qEAAqE,CAAC;AAClG,eAAO,MAAM,cAAc,yCAAyC,CAAC;AAUrE,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAuD7C;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,kBAAkB,GAAG,IAAI,CAuB/G;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAKjE;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,EACZ,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAmBR;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,EACZ,GAAG,GAAE,MAAM,MAAiB,EAC5B,KAAK,GAAE,KAAiE,GACvE,OAAO,CAAC,kBAAkB,CAAC,CAsC7B;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GACnD,IAAI,CAaN;AA0GD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,cAAmB,GAC3D,OAAO,CAAC,iBAAiB,CAAC,CAa5B"}
@@ -0,0 +1,411 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.APPROVAL_GRACE_MS = exports.DENIED_MESSAGE = exports.EXPIRED_MESSAGE = exports.DeviceLoginStoppedError = exports.DeviceFlowUnavailableError = void 0;
37
+ exports.readPendingDeviceLogin = readPendingDeviceLogin;
38
+ exports.clearPendingDeviceLogin = clearPendingDeviceLogin;
39
+ exports.deviceLink = deviceLink;
40
+ exports.chooseDeviceLink = chooseDeviceLink;
41
+ exports.startDeviceLogin = startDeviceLogin;
42
+ exports.printDeviceInstructions = printDeviceInstructions;
43
+ exports.waitForDeviceLogin = waitForDeviceLogin;
44
+ exports.runDeviceFlow = runDeviceFlow;
45
+ /**
46
+ * Device sign-in (GOOSE-3937) — the "TV login" pattern (RFC 8628 shape).
47
+ *
48
+ * The CLI asks the server for a short code, prints a link, and the user
49
+ * approves on any device. The CLI then collects its key by polling. Nothing
50
+ * travels through localhost, so this works when the shell runs in a cloud
51
+ * sandbox or over SSH and the browser is on a phone or laptop.
52
+ *
53
+ * `--no-wait` prints the link and exits; the pending request is saved in the
54
+ * profile dir so the next sign-in (e.g. `install --skills-only`) resumes it.
55
+ */
56
+ const fs = __importStar(require("fs"));
57
+ const path = __importStar(require("path"));
58
+ const config_1 = require("../config");
59
+ const environment_1 = require("../environment");
60
+ const http_1 = require("../utils/http");
61
+ const logger = __importStar(require("../utils/logger"));
62
+ const credentials_1 = require("./credentials");
63
+ /** The server predates device sign-in (`/api/cli/device/start` returned 404). */
64
+ class DeviceFlowUnavailableError extends Error {
65
+ constructor() {
66
+ super("Device sign-in isn't available on this server yet.");
67
+ this.name = 'DeviceFlowUnavailableError';
68
+ }
69
+ }
70
+ exports.DeviceFlowUnavailableError = DeviceFlowUnavailableError;
71
+ /** Ctrl-C / SIGTERM while waiting. The pending request is kept so a rerun resumes. */
72
+ class DeviceLoginStoppedError extends Error {
73
+ constructor() {
74
+ super('Stopped waiting for sign-in. Run the command again to finish; the same link works until it expires.');
75
+ this.name = 'DeviceLoginStoppedError';
76
+ }
77
+ }
78
+ exports.DeviceLoginStoppedError = DeviceLoginStoppedError;
79
+ exports.EXPIRED_MESSAGE = 'This sign-in code expired. Run the command again for a new link.';
80
+ exports.DENIED_MESSAGE = 'Sign-in was canceled in the browser.';
81
+ const REQUEST_TIMEOUT_MS = 15_000;
82
+ // The collecting poll mints the key (and, for a new user, their workspace and
83
+ // credits), so give it longer than the other calls.
84
+ const POLL_TIMEOUT_MS = 60_000;
85
+ // The server gives an approval its own 10 minutes to be collected, because in
86
+ // a cloud agent the user approves and then has to go back and tell the agent.
87
+ // So a saved request stays usable this long past its own expiry; the server
88
+ // says "expired" if it really is.
89
+ exports.APPROVAL_GRACE_MS = 10 * 60_000;
90
+ const DEFAULT_EXPIRES_IN_S = 600;
91
+ const DEFAULT_INTERVAL_S = 3;
92
+ const MAX_INTERVAL_S = 60;
93
+ function pendingFile() {
94
+ return path.join((0, environment_1.profileRoot)(), 'pending-login.json');
95
+ }
96
+ function trimBase(apiBase) {
97
+ return apiBase.replace(/\/+$/, '');
98
+ }
99
+ function saneInterval(value, fallback) {
100
+ const n = Number(value);
101
+ if (!Number.isFinite(n) || n <= 0)
102
+ return fallback;
103
+ return Math.min(Math.max(n, 1), MAX_INTERVAL_S);
104
+ }
105
+ function savePendingDeviceLogin(pending) {
106
+ const dir = (0, environment_1.profileRoot)();
107
+ if (!fs.existsSync(dir))
108
+ fs.mkdirSync(dir, { mode: 0o700, recursive: true });
109
+ fs.writeFileSync(pendingFile(), JSON.stringify(pending, null, 2) + '\n', { mode: 0o600 });
110
+ fs.chmodSync(dir, 0o700);
111
+ fs.chmodSync(pendingFile(), 0o600);
112
+ }
113
+ /**
114
+ * The saved device sign-in for `apiBase`, or null when the file is missing,
115
+ * broken, expired, or belongs to another API base.
116
+ */
117
+ function readPendingDeviceLogin(apiBase, now = Date.now) {
118
+ try {
119
+ const parsed = JSON.parse(fs.readFileSync(pendingFile(), 'utf-8'));
120
+ if (typeof parsed.device_code !== 'string' || !parsed.device_code ||
121
+ typeof parsed.user_code !== 'string' || !parsed.user_code ||
122
+ typeof parsed.link !== 'string' || !parsed.link ||
123
+ typeof parsed.api_base !== 'string' || typeof parsed.expires_at !== 'string')
124
+ return null;
125
+ if (trimBase(parsed.api_base) !== trimBase(apiBase))
126
+ return null;
127
+ const expiresAt = Date.parse(parsed.expires_at);
128
+ if (!Number.isFinite(expiresAt) || expiresAt + exports.APPROVAL_GRACE_MS <= now())
129
+ return null;
130
+ return {
131
+ device_code: parsed.device_code,
132
+ user_code: parsed.user_code,
133
+ link: parsed.link,
134
+ api_base: parsed.api_base,
135
+ expires_at: parsed.expires_at,
136
+ interval: saneInterval(parsed.interval, DEFAULT_INTERVAL_S),
137
+ };
138
+ }
139
+ catch {
140
+ return null;
141
+ }
142
+ }
143
+ function clearPendingDeviceLogin() {
144
+ try {
145
+ if (fs.existsSync(pendingFile()))
146
+ fs.unlinkSync(pendingFile());
147
+ }
148
+ catch {
149
+ // Ignore errors during cleanup
150
+ }
151
+ }
152
+ /**
153
+ * The link the user opens. Built from the CLI's own FRONTEND_URL (the same
154
+ * source `/cli/auth` uses) so local/staging overrides keep working.
155
+ */
156
+ function deviceLink(userCode, ref) {
157
+ let link = `${config_1.FRONTEND_URL}/link?code=${encodeURIComponent(userCode)}`;
158
+ const trimmed = ref?.trim();
159
+ if (trimmed)
160
+ link += `&creator_ref=${encodeURIComponent(trimmed)}`;
161
+ return link;
162
+ }
163
+ function isLocalHost(hostname) {
164
+ return ['localhost', '127.0.0.1', '[::1]'].includes(hostname);
165
+ }
166
+ /**
167
+ * The link to print for a new code. An explicit GOOSEWORKS_FRONTEND_URL (local
168
+ * testing) wins. Otherwise the server's own `verification_url_complete`: it
169
+ * knows which Growth app serves /link in its environment (make.gooseworks.ai
170
+ * in production, ads-staging.gooseworks.ai on staging), which the CLI's
171
+ * FRONTEND_URL does not (staging's points at the old GTM app). It is used only
172
+ * when it is an https GooseWorks address, or a local one for a local API;
173
+ * anything else falls back to FRONTEND_URL.
174
+ */
175
+ function chooseDeviceLink(serverLink, userCode, apiBase, ref, env = process.env) {
176
+ if (env.GOOSEWORKS_FRONTEND_URL?.trim() || typeof serverLink !== 'string')
177
+ return deviceLink(userCode, ref);
178
+ let url;
179
+ try {
180
+ url = new URL(serverLink);
181
+ }
182
+ catch {
183
+ return deviceLink(userCode, ref);
184
+ }
185
+ const gooseworks = url.protocol === 'https:' && (url.hostname === 'gooseworks.ai' || url.hostname.endsWith('.gooseworks.ai'));
186
+ let localApi = false;
187
+ try {
188
+ localApi = isLocalHost(new URL(apiBase).hostname);
189
+ }
190
+ catch { /* not local */ }
191
+ const local = localApi && isLocalHost(url.hostname) && (url.protocol === 'http:' || url.protocol === 'https:');
192
+ if ((!gooseworks && !local) || url.username || url.password || url.hash || url.pathname.replace(/\/+$/, '') !== '/link') {
193
+ return deviceLink(userCode, ref);
194
+ }
195
+ // Same encoding as deviceLink(), so both paths print identical links.
196
+ const trimmed = ref?.trim();
197
+ url.search = `?code=${encodeURIComponent(userCode)}${trimmed ? `&creator_ref=${encodeURIComponent(trimmed)}` : ''}`;
198
+ return url.toString();
199
+ }
200
+ async function startDeviceLogin(apiBase, ref, now = Date.now, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
201
+ let res;
202
+ // Cloud agents share egress IPs, so a busy platform can hit the per-IP
203
+ // limit: back off and try a couple more times.
204
+ for (let attempt = 1; !res; attempt++) {
205
+ try {
206
+ res = await (0, http_1.requestJson)({
207
+ apiBase: trimBase(apiBase),
208
+ method: 'POST',
209
+ path: '/api/cli/device/start',
210
+ body: { scope_type: 'user' },
211
+ timeoutMs: REQUEST_TIMEOUT_MS,
212
+ });
213
+ }
214
+ catch (err) {
215
+ if (err instanceof http_1.HttpError && err.status === 404)
216
+ throw new DeviceFlowUnavailableError();
217
+ if (err instanceof http_1.HttpError && err.status === 429 && attempt < 3) {
218
+ await sleep(attempt * 2000);
219
+ continue;
220
+ }
221
+ throw err;
222
+ }
223
+ }
224
+ const data = res?.data;
225
+ if (!data || typeof data.device_code !== 'string' || !data.device_code || typeof data.user_code !== 'string' || !data.user_code) {
226
+ throw new Error('The server did not return a sign-in code. Please try again.');
227
+ }
228
+ const expiresInRaw = Number(data.expires_in);
229
+ const expiresIn = Number.isFinite(expiresInRaw) && expiresInRaw > 0 ? expiresInRaw : DEFAULT_EXPIRES_IN_S;
230
+ const pending = {
231
+ device_code: data.device_code,
232
+ user_code: data.user_code,
233
+ link: chooseDeviceLink(data.verification_url_complete, data.user_code, apiBase, ref),
234
+ api_base: apiBase,
235
+ expires_at: new Date(now() + expiresIn * 1000).toISOString(),
236
+ interval: saneInterval(data.interval, DEFAULT_INTERVAL_S),
237
+ };
238
+ savePendingDeviceLogin(pending);
239
+ return pending;
240
+ }
241
+ /** Prints the link and code. Never opens a browser. */
242
+ function printDeviceInstructions(pending, opts = {}) {
243
+ const now = opts.now ?? Date.now;
244
+ const left = Date.parse(pending.expires_at) - now();
245
+ const heading = opts.resumed ? 'Still waiting for you to approve:' : 'Sign in to GooseWorks from any device:';
246
+ logger.info(`${heading}\n ${pending.link}`);
247
+ if (left > 0) {
248
+ const minutes = Math.max(1, Math.ceil(left / 60_000));
249
+ logger.info(`Code: ${pending.user_code} (expires in ${minutes} minute${minutes === 1 ? '' : 's'})`);
250
+ }
251
+ else {
252
+ // Past its approval deadline but inside the collection grace: the server
253
+ // still hands over the key if the user approved in time.
254
+ logger.info(`Code: ${pending.user_code}`);
255
+ }
256
+ }
257
+ const defaultSleep = (ms, signal) => new Promise((resolve) => {
258
+ const onAbort = () => { clearTimeout(timer); resolve(); };
259
+ const timer = setTimeout(() => {
260
+ signal?.removeEventListener('abort', onAbort);
261
+ resolve();
262
+ }, ms);
263
+ signal?.addEventListener('abort', onAbort, { once: true });
264
+ });
265
+ function credentialsFromPoll(apiBase, data) {
266
+ if (!data || typeof data.token !== 'string' || !data.token || typeof data.email !== 'string' || !data.email || typeof data.agent_id !== 'string' || !data.agent_id) {
267
+ throw new Error('The server sent an incomplete sign-in. Run the command again for a new link.');
268
+ }
269
+ const scopeType = data.scope_type === 'agent' || data.scope_type === 'user' ? data.scope_type : undefined;
270
+ return {
271
+ api_key: data.token,
272
+ email: data.email,
273
+ agent_id: data.agent_id,
274
+ api_base: data.api_base || apiBase,
275
+ ...(scopeType ? { scope_type: scopeType } : {}),
276
+ ...(data.default_agent_id ? { default_agent_id: data.default_agent_id } : {}),
277
+ ...(data.mcp_server_url ? { mcp_server_url: data.mcp_server_url } : {}),
278
+ };
279
+ }
280
+ /** One poll. Saves the key on success; never throws for a server answer. */
281
+ async function pollOnce(apiBase, pending, interval, guard = (work) => work) {
282
+ let res;
283
+ try {
284
+ res = await guard((0, http_1.requestJson)({
285
+ apiBase: trimBase(apiBase),
286
+ method: 'POST',
287
+ path: '/api/cli/device/poll',
288
+ body: { device_code: pending.device_code },
289
+ timeoutMs: POLL_TIMEOUT_MS,
290
+ }));
291
+ }
292
+ catch (err) {
293
+ if (err instanceof DeviceLoginStoppedError)
294
+ throw err;
295
+ if (err instanceof http_1.HttpError && err.status === 404) {
296
+ clearPendingDeviceLogin();
297
+ return { kind: 'gone', message: exports.EXPIRED_MESSAGE };
298
+ }
299
+ if (err instanceof http_1.HttpError && err.status === 429) {
300
+ return { kind: 'waiting', interval: Math.min(interval + 2, MAX_INTERVAL_S) };
301
+ }
302
+ if (err instanceof http_1.HttpError && err.status >= 400 && err.status < 500) {
303
+ clearPendingDeviceLogin();
304
+ return { kind: 'gone', message: `Sign-in failed (status ${err.status}). Run the command again for a new link.` };
305
+ }
306
+ // 5xx, timeouts and network errors are transient.
307
+ return { kind: 'waiting', interval };
308
+ }
309
+ switch (res?.status) {
310
+ case 'success': {
311
+ // The code is single-use: once collected, the pending file is useless.
312
+ try {
313
+ const creds = credentialsFromPoll(apiBase, res.data);
314
+ if ((0, environment_1.getEnvironment)() === 'staging' && (!res.data?.api_base || new URL(res.data.api_base).origin !== new URL(apiBase).origin)) {
315
+ throw new Error('The sign-in did not confirm the staging API');
316
+ }
317
+ (0, credentials_1.validateCredentials)(creds);
318
+ (0, credentials_1.saveCredentials)(creds);
319
+ return {
320
+ kind: 'done',
321
+ result: {
322
+ api_key: creds.api_key,
323
+ email: creds.email,
324
+ agent_id: creds.agent_id,
325
+ ...(creds.scope_type ? { scope_type: creds.scope_type } : {}),
326
+ ...(creds.default_agent_id ? { default_agent_id: creds.default_agent_id } : {}),
327
+ ...(creds.mcp_server_url ? { mcp_server_url: creds.mcp_server_url } : {}),
328
+ },
329
+ };
330
+ }
331
+ finally {
332
+ clearPendingDeviceLogin();
333
+ }
334
+ }
335
+ case 'expired':
336
+ clearPendingDeviceLogin();
337
+ return { kind: 'gone', message: exports.EXPIRED_MESSAGE };
338
+ case 'denied':
339
+ clearPendingDeviceLogin();
340
+ return { kind: 'gone', message: exports.DENIED_MESSAGE };
341
+ case 'slow_down':
342
+ return { kind: 'waiting', interval: saneInterval(res.interval, Math.min(interval + 2, MAX_INTERVAL_S)) };
343
+ default:
344
+ // 'pending' (and anything unrecognised): keep the server's pace.
345
+ return { kind: 'waiting', interval: saneInterval(res?.interval, interval) };
346
+ }
347
+ }
348
+ /**
349
+ * Polls until the user approves, denies, or the code expires. On success the
350
+ * key is saved like a browser sign-in and the pending file is removed. The
351
+ * server decides expiry; the local cut-off (expiry plus the approval grace)
352
+ * only stops a server that never answers.
353
+ */
354
+ async function waitForDeviceLogin(apiBase, pending, deps = {}) {
355
+ const sleep = deps.sleep ?? defaultSleep;
356
+ const now = deps.now ?? Date.now;
357
+ const giveUpAt = Date.parse(pending.expires_at) + exports.APPROVAL_GRACE_MS;
358
+ let interval = saneInterval(pending.interval, DEFAULT_INTERVAL_S);
359
+ const controller = new AbortController();
360
+ const stopped = new Promise((_, reject) => {
361
+ controller.signal.addEventListener('abort', () => reject(new DeviceLoginStoppedError()), { once: true });
362
+ });
363
+ stopped.catch(() => undefined);
364
+ const guard = (work) => Promise.race([work, stopped]);
365
+ const onSignal = () => controller.abort();
366
+ process.once('SIGINT', onSignal);
367
+ process.once('SIGTERM', onSignal);
368
+ try {
369
+ for (;;) {
370
+ const step = await pollOnce(apiBase, pending, interval, guard);
371
+ if (step.kind === 'done')
372
+ return step.result;
373
+ if (step.kind === 'gone')
374
+ throw new Error(step.message);
375
+ interval = step.interval;
376
+ if (!(now() < giveUpAt)) {
377
+ clearPendingDeviceLogin();
378
+ throw new Error(exports.EXPIRED_MESSAGE);
379
+ }
380
+ await guard(sleep(interval * 1000, controller.signal));
381
+ }
382
+ }
383
+ finally {
384
+ process.removeListener('SIGINT', onSignal);
385
+ process.removeListener('SIGTERM', onSignal);
386
+ }
387
+ }
388
+ /**
389
+ * Resume a saved request for this API base, or start a new one; print the
390
+ * link; then either return at once (`wait: false`) or wait for approval.
391
+ * Resuming with `wait: false` asks the server first, so it never re-prints a
392
+ * code that was already approved, canceled or used.
393
+ */
394
+ async function runDeviceFlow(apiBase, opts = {}) {
395
+ const now = opts.now ?? Date.now;
396
+ let existing = readPendingDeviceLogin(apiBase, now);
397
+ if (existing && opts.wait === false) {
398
+ const step = await pollOnce(apiBase, existing, existing.interval);
399
+ if (step.kind === 'done')
400
+ return { status: 'done', result: step.result };
401
+ if (step.kind === 'gone')
402
+ existing = null;
403
+ }
404
+ const pending = existing ?? await startDeviceLogin(apiBase, opts.ref, now, opts.sleep);
405
+ printDeviceInstructions(pending, { resumed: existing !== null, now });
406
+ if (opts.wait === false)
407
+ return { status: 'pending', pending };
408
+ const result = await waitForDeviceLogin(apiBase, pending, { sleep: opts.sleep, now });
409
+ return { status: 'done', result };
410
+ }
411
+ //# sourceMappingURL=device-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-flow.js","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export type LoginMode = 'device' | 'browser';
2
+ export interface LoginModeOptions {
3
+ /** `--device` */
4
+ device?: boolean;
5
+ /** `--browser` */
6
+ browser?: boolean;
7
+ /** `--no-wait` (only makes sense with device sign-in). */
8
+ noWait?: boolean;
9
+ /** A saved, unexpired device sign-in exists for this API base. */
10
+ pendingLogin?: boolean;
11
+ }
12
+ /**
13
+ * Picks browser (localhost callback) or device (code + link) sign-in.
14
+ *
15
+ * Explicit flags win, then `GOOSEWORKS_LOGIN`, then a pending device sign-in,
16
+ * then environment heuristics that only fire where a local browser can't reach
17
+ * the CLI (SSH, CI, Linux with no display, containers). macOS/Windows desktops
18
+ * always get the browser flow by default. We can't rely on `open()` failing:
19
+ * open@7 resolves on Linux even with no browser.
20
+ */
21
+ export declare function chooseLoginMode(opts: LoginModeOptions, env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, exists?: (file: string) => boolean, readFile?: (file: string) => string): {
22
+ mode: LoginMode;
23
+ reason: string;
24
+ };
25
+ //# sourceMappingURL=login-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-mode.d.ts","sourceRoot":"","sources":["../../src/auth/login-mode.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,gBAAgB,EACtB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAuB,EACjD,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAiD,GAC5E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAuBrC"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.chooseLoginMode = chooseLoginMode;
37
+ const fs = __importStar(require("fs"));
38
+ function truthy(value) {
39
+ if (value === undefined)
40
+ return false;
41
+ const v = value.trim().toLowerCase();
42
+ return v !== '' && v !== '0' && v !== 'false';
43
+ }
44
+ function isWsl(env, readFile) {
45
+ if (env.WSL_DISTRO_NAME)
46
+ return true;
47
+ try {
48
+ return readFile('/proc/version').toLowerCase().includes('microsoft');
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ /**
55
+ * Picks browser (localhost callback) or device (code + link) sign-in.
56
+ *
57
+ * Explicit flags win, then `GOOSEWORKS_LOGIN`, then a pending device sign-in,
58
+ * then environment heuristics that only fire where a local browser can't reach
59
+ * the CLI (SSH, CI, Linux with no display, containers). macOS/Windows desktops
60
+ * always get the browser flow by default. We can't rely on `open()` failing:
61
+ * open@7 resolves on Linux even with no browser.
62
+ */
63
+ function chooseLoginMode(opts, env = process.env, platform = process.platform, exists = fs.existsSync, readFile = (file) => fs.readFileSync(file, 'utf-8')) {
64
+ if (opts.device)
65
+ return { mode: 'device', reason: '--device' };
66
+ if (opts.noWait)
67
+ return { mode: 'device', reason: '--no-wait' };
68
+ if (opts.browser)
69
+ return { mode: 'browser', reason: '--browser' };
70
+ const forced = env.GOOSEWORKS_LOGIN?.trim().toLowerCase();
71
+ if (forced === 'device' || forced === 'browser')
72
+ return { mode: forced, reason: `GOOSEWORKS_LOGIN=${forced}` };
73
+ if (opts.pendingLogin)
74
+ return { mode: 'device', reason: 'resuming a pending device sign-in' };
75
+ if (env.SSH_CONNECTION || env.SSH_CLIENT || env.SSH_TTY)
76
+ return { mode: 'device', reason: 'SSH session' };
77
+ if (truthy(env.CI))
78
+ return { mode: 'device', reason: 'CI environment' };
79
+ if (platform === 'linux' && !env.DISPLAY && !env.WAYLAND_DISPLAY && !isWsl(env, readFile)) {
80
+ return { mode: 'device', reason: 'Linux without a display' };
81
+ }
82
+ if (exists('/.dockerenv') || exists('/run/.containerenv') || env.container || env.KUBERNETES_SERVICE_HOST) {
83
+ return { mode: 'device', reason: 'container' };
84
+ }
85
+ return { mode: 'browser', reason: 'default' };
86
+ }
87
+ //# sourceMappingURL=login-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-mode.js","sourceRoot":"","sources":["../../src/auth/login-mode.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,0CA6BC;AApED,uCAAyB;AAezB,SAAS,MAAM,CAAC,KAAyB;IACvC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,OAAO,CAAC;AAChD,CAAC;AAED,SAAS,KAAK,CAAC,GAAsB,EAAE,QAAkC;IACvE,IAAI,GAAG,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,eAAe,CAC7B,IAAsB,EACtB,MAAyB,OAAO,CAAC,GAAG,EACpC,WAA4B,OAAO,CAAC,QAAQ,EAC5C,SAAoC,EAAE,CAAC,UAAU,EACjD,WAAqC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;IAE7E,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAChE,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAElE,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1D,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,MAAM,EAAE,EAAE,CAAC;IAE/G,IAAI,IAAI,CAAC,YAAY;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC;IAE9F,IAAI,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAE1G,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAExE,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC1F,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,MAAM,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,oBAAoB,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,uBAAuB,EAAE,CAAC;QAC1G,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAChD,CAAC"}
@@ -1,4 +1,5 @@
1
- interface OAuthResult {
1
+ export declare const OAUTH_TIMEOUT_MS = 300000;
2
+ export interface OAuthResult {
2
3
  api_key: string;
3
4
  email: string;
4
5
  agent_id: string;
@@ -14,5 +15,4 @@ interface OAuthResult {
14
15
  * authenticated attribution call.
15
16
  */
16
17
  export declare function runOAuthFlow(apiBase: string, attributionRef?: string): Promise<OAuthResult>;
17
- export {};
18
18
  //# sourceMappingURL=oauth-server.d.ts.map