gooseworks 0.5.0-dev.5.1ff84a4f → 0.5.0-dev.8.6854a9a6
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 +15 -1
- package/dist/auth/device-flow.d.ts +69 -0
- package/dist/auth/device-flow.d.ts.map +1 -0
- package/dist/auth/device-flow.js +373 -0
- package/dist/auth/device-flow.js.map +1 -0
- package/dist/auth/login-mode.d.ts +25 -0
- package/dist/auth/login-mode.d.ts.map +1 -0
- package/dist/auth/login-mode.js +87 -0
- package/dist/auth/login-mode.js.map +1 -0
- package/dist/auth/oauth-server.d.ts +2 -2
- package/dist/auth/oauth-server.d.ts.map +1 -1
- package/dist/auth/oauth-server.js +10 -3
- package/dist/auth/oauth-server.js.map +1 -1
- package/dist/auth/paste-login.d.ts +27 -0
- package/dist/auth/paste-login.d.ts.map +1 -0
- package/dist/auth/paste-login.js +203 -0
- package/dist/auth/paste-login.js.map +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +81 -34
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts +21 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +100 -30
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +4 -0
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/tool.d.ts +17 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/tool.js +239 -0
- package/dist/commands/tool.js.map +1 -0
- package/dist/lib/mcp-client.d.ts +53 -0
- package/dist/lib/mcp-client.d.ts.map +1 -0
- package/dist/lib/mcp-client.js +196 -0
- package/dist/lib/mcp-client.js.map +1 -0
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +2 -0
- package/dist/program.js.map +1 -1
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +41 -4
- package/dist/skills/master-skill.js.map +1 -1
- package/dist/utils/http.d.ts +7 -1
- package/dist/utils/http.d.ts.map +1 -1
- package/dist/utils/http.js +5 -1
- package/dist/utils/http.js.map +1 -1
- package/package.json +2 -2
- package/skills/goose-ads/SKILL.md +23 -0
- package/skills/goose-product-photos/SKILL.md +23 -0
- package/skills/goose-video/SKILL.md +23 -0
- package/skills/goose-video-local/SKILL.md +23 -0
- package/skills/gooseworks/SKILL.md +28 -3
- package/skills/make-custom-video/SKILL.md +23 -0
- package/skills/manifest.json +7 -7
package/README.md
CHANGED
|
@@ -107,7 +107,9 @@ npx gooseworks login
|
|
|
107
107
|
3. You sign in with Google
|
|
108
108
|
4. Token saved to `~/.gooseworks/credentials.json`
|
|
109
109
|
|
|
110
|
-
Timeout:
|
|
110
|
+
Timeout: 5 minutes. The sign-in link is always printed, so you can open it yourself if no browser opens.
|
|
111
|
+
|
|
112
|
+
**Cloud agents, SSH and CI** (the browser is on another device): run `npx gooseworks login --device`. It prints a link and a code; open the link on any device, sign in and tap **Approve**, and the CLI finishes on its own. The CLI picks this mode by itself over SSH, in CI, in containers and on Linux with no display (`--browser` forces the browser flow). Agents whose shell only shows output when a command exits should add `--no-wait`: it prints the link and exits, and the next `gooseworks login` or `gooseworks install --skills-only` finishes the sign-in once you approve.
|
|
111
113
|
|
|
112
114
|
### `logout`
|
|
113
115
|
|
|
@@ -235,6 +237,18 @@ npx gooseworks call scrapecreators /v1/facebook/adLibrary/search/ads \
|
|
|
235
237
|
--body='{"query":"running shoes","country":"US"}'
|
|
236
238
|
```
|
|
237
239
|
|
|
240
|
+
### `tool`
|
|
241
|
+
|
|
242
|
+
Call any GooseWorks tool (the same tools the GooseWorks MCP connector gives an agent) with your saved sign-in. It's meant for agents that have a shell but no connector, such as a cloud sandbox in ChatGPT agent, Meta AI or Grok:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
npx gooseworks tool --list # the server's rules + every tool
|
|
246
|
+
npx gooseworks tool brand_onboarding --schema # one tool's arguments
|
|
247
|
+
npx gooseworks tool brand_onboarding '{"action":"status"}' # call it
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The result prints as JSON (`--json` prints the raw MCP result). Arguments can also come from a file (`--file args.json`) or stdin (`-`). It exits 1 when the tool reports an error. Paid tools follow the same rules as over the connector.
|
|
251
|
+
|
|
238
252
|
## Security & data handling
|
|
239
253
|
|
|
240
254
|
We'd rather you know exactly what this CLI does before you run it:
|
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
export declare function startDeviceLogin(apiBase: string, ref?: string, now?: () => number, sleep?: Sleep): Promise<PendingDeviceLogin>;
|
|
47
|
+
/** Prints the link and code. Never opens a browser. */
|
|
48
|
+
export declare function printDeviceInstructions(pending: PendingDeviceLogin, opts?: {
|
|
49
|
+
resumed?: boolean;
|
|
50
|
+
now?: () => number;
|
|
51
|
+
}): void;
|
|
52
|
+
/**
|
|
53
|
+
* Polls until the user approves, denies, or the code expires. On success the
|
|
54
|
+
* key is saved like a browser sign-in and the pending file is removed. The
|
|
55
|
+
* server decides expiry; the local cut-off (expiry plus the approval grace)
|
|
56
|
+
* only stops a server that never answers.
|
|
57
|
+
*/
|
|
58
|
+
export declare function waitForDeviceLogin(apiBase: string, pending: PendingDeviceLogin, deps?: DeviceWaitDeps): Promise<OAuthResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Resume a saved request for this API base, or start a new one; print the
|
|
61
|
+
* link; then either return at once (`wait: false`) or wait for approval.
|
|
62
|
+
* Resuming with `wait: false` asks the server first, so it never re-prints a
|
|
63
|
+
* code that was already approved, canceled or used.
|
|
64
|
+
*/
|
|
65
|
+
export declare function runDeviceFlow(apiBase: string, opts?: {
|
|
66
|
+
ref?: string;
|
|
67
|
+
wait?: boolean;
|
|
68
|
+
} & DeviceWaitDeps): Promise<DeviceFlowOutcome>;
|
|
69
|
+
//# 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;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,373 @@
|
|
|
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.startDeviceLogin = startDeviceLogin;
|
|
41
|
+
exports.printDeviceInstructions = printDeviceInstructions;
|
|
42
|
+
exports.waitForDeviceLogin = waitForDeviceLogin;
|
|
43
|
+
exports.runDeviceFlow = runDeviceFlow;
|
|
44
|
+
/**
|
|
45
|
+
* Device sign-in (GOOSE-3937) — the "TV login" pattern (RFC 8628 shape).
|
|
46
|
+
*
|
|
47
|
+
* The CLI asks the server for a short code, prints a link, and the user
|
|
48
|
+
* approves on any device. The CLI then collects its key by polling. Nothing
|
|
49
|
+
* travels through localhost, so this works when the shell runs in a cloud
|
|
50
|
+
* sandbox or over SSH and the browser is on a phone or laptop.
|
|
51
|
+
*
|
|
52
|
+
* `--no-wait` prints the link and exits; the pending request is saved in the
|
|
53
|
+
* profile dir so the next sign-in (e.g. `install --skills-only`) resumes it.
|
|
54
|
+
*/
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
const config_1 = require("../config");
|
|
58
|
+
const environment_1 = require("../environment");
|
|
59
|
+
const http_1 = require("../utils/http");
|
|
60
|
+
const logger = __importStar(require("../utils/logger"));
|
|
61
|
+
const credentials_1 = require("./credentials");
|
|
62
|
+
/** The server predates device sign-in (`/api/cli/device/start` returned 404). */
|
|
63
|
+
class DeviceFlowUnavailableError extends Error {
|
|
64
|
+
constructor() {
|
|
65
|
+
super("Device sign-in isn't available on this server yet.");
|
|
66
|
+
this.name = 'DeviceFlowUnavailableError';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.DeviceFlowUnavailableError = DeviceFlowUnavailableError;
|
|
70
|
+
/** Ctrl-C / SIGTERM while waiting. The pending request is kept so a rerun resumes. */
|
|
71
|
+
class DeviceLoginStoppedError extends Error {
|
|
72
|
+
constructor() {
|
|
73
|
+
super('Stopped waiting for sign-in. Run the command again to finish; the same link works until it expires.');
|
|
74
|
+
this.name = 'DeviceLoginStoppedError';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.DeviceLoginStoppedError = DeviceLoginStoppedError;
|
|
78
|
+
exports.EXPIRED_MESSAGE = 'This sign-in code expired. Run the command again for a new link.';
|
|
79
|
+
exports.DENIED_MESSAGE = 'Sign-in was canceled in the browser.';
|
|
80
|
+
const REQUEST_TIMEOUT_MS = 15_000;
|
|
81
|
+
// The collecting poll mints the key (and, for a new user, their workspace and
|
|
82
|
+
// credits), so give it longer than the other calls.
|
|
83
|
+
const POLL_TIMEOUT_MS = 60_000;
|
|
84
|
+
// The server gives an approval its own 10 minutes to be collected, because in
|
|
85
|
+
// a cloud agent the user approves and then has to go back and tell the agent.
|
|
86
|
+
// So a saved request stays usable this long past its own expiry; the server
|
|
87
|
+
// says "expired" if it really is.
|
|
88
|
+
exports.APPROVAL_GRACE_MS = 10 * 60_000;
|
|
89
|
+
const DEFAULT_EXPIRES_IN_S = 600;
|
|
90
|
+
const DEFAULT_INTERVAL_S = 3;
|
|
91
|
+
const MAX_INTERVAL_S = 60;
|
|
92
|
+
function pendingFile() {
|
|
93
|
+
return path.join((0, environment_1.profileRoot)(), 'pending-login.json');
|
|
94
|
+
}
|
|
95
|
+
function trimBase(apiBase) {
|
|
96
|
+
return apiBase.replace(/\/+$/, '');
|
|
97
|
+
}
|
|
98
|
+
function saneInterval(value, fallback) {
|
|
99
|
+
const n = Number(value);
|
|
100
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
101
|
+
return fallback;
|
|
102
|
+
return Math.min(Math.max(n, 1), MAX_INTERVAL_S);
|
|
103
|
+
}
|
|
104
|
+
function savePendingDeviceLogin(pending) {
|
|
105
|
+
const dir = (0, environment_1.profileRoot)();
|
|
106
|
+
if (!fs.existsSync(dir))
|
|
107
|
+
fs.mkdirSync(dir, { mode: 0o700, recursive: true });
|
|
108
|
+
fs.writeFileSync(pendingFile(), JSON.stringify(pending, null, 2) + '\n', { mode: 0o600 });
|
|
109
|
+
fs.chmodSync(dir, 0o700);
|
|
110
|
+
fs.chmodSync(pendingFile(), 0o600);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The saved device sign-in for `apiBase`, or null when the file is missing,
|
|
114
|
+
* broken, expired, or belongs to another API base.
|
|
115
|
+
*/
|
|
116
|
+
function readPendingDeviceLogin(apiBase, now = Date.now) {
|
|
117
|
+
try {
|
|
118
|
+
const parsed = JSON.parse(fs.readFileSync(pendingFile(), 'utf-8'));
|
|
119
|
+
if (typeof parsed.device_code !== 'string' || !parsed.device_code ||
|
|
120
|
+
typeof parsed.user_code !== 'string' || !parsed.user_code ||
|
|
121
|
+
typeof parsed.link !== 'string' || !parsed.link ||
|
|
122
|
+
typeof parsed.api_base !== 'string' || typeof parsed.expires_at !== 'string')
|
|
123
|
+
return null;
|
|
124
|
+
if (trimBase(parsed.api_base) !== trimBase(apiBase))
|
|
125
|
+
return null;
|
|
126
|
+
const expiresAt = Date.parse(parsed.expires_at);
|
|
127
|
+
if (!Number.isFinite(expiresAt) || expiresAt + exports.APPROVAL_GRACE_MS <= now())
|
|
128
|
+
return null;
|
|
129
|
+
return {
|
|
130
|
+
device_code: parsed.device_code,
|
|
131
|
+
user_code: parsed.user_code,
|
|
132
|
+
link: parsed.link,
|
|
133
|
+
api_base: parsed.api_base,
|
|
134
|
+
expires_at: parsed.expires_at,
|
|
135
|
+
interval: saneInterval(parsed.interval, DEFAULT_INTERVAL_S),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function clearPendingDeviceLogin() {
|
|
143
|
+
try {
|
|
144
|
+
if (fs.existsSync(pendingFile()))
|
|
145
|
+
fs.unlinkSync(pendingFile());
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Ignore errors during cleanup
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The link the user opens. Built from the CLI's own FRONTEND_URL (the same
|
|
153
|
+
* source `/cli/auth` uses) so local/staging overrides keep working.
|
|
154
|
+
*/
|
|
155
|
+
function deviceLink(userCode, ref) {
|
|
156
|
+
let link = `${config_1.FRONTEND_URL}/link?code=${encodeURIComponent(userCode)}`;
|
|
157
|
+
const trimmed = ref?.trim();
|
|
158
|
+
if (trimmed)
|
|
159
|
+
link += `&creator_ref=${encodeURIComponent(trimmed)}`;
|
|
160
|
+
return link;
|
|
161
|
+
}
|
|
162
|
+
async function startDeviceLogin(apiBase, ref, now = Date.now, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
|
|
163
|
+
let res;
|
|
164
|
+
// Cloud agents share egress IPs, so a busy platform can hit the per-IP
|
|
165
|
+
// limit: back off and try a couple more times.
|
|
166
|
+
for (let attempt = 1; !res; attempt++) {
|
|
167
|
+
try {
|
|
168
|
+
res = await (0, http_1.requestJson)({
|
|
169
|
+
apiBase: trimBase(apiBase),
|
|
170
|
+
method: 'POST',
|
|
171
|
+
path: '/api/cli/device/start',
|
|
172
|
+
body: { scope_type: 'user' },
|
|
173
|
+
timeoutMs: REQUEST_TIMEOUT_MS,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
if (err instanceof http_1.HttpError && err.status === 404)
|
|
178
|
+
throw new DeviceFlowUnavailableError();
|
|
179
|
+
if (err instanceof http_1.HttpError && err.status === 429 && attempt < 3) {
|
|
180
|
+
await sleep(attempt * 2000);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const data = res?.data;
|
|
187
|
+
if (!data || typeof data.device_code !== 'string' || !data.device_code || typeof data.user_code !== 'string' || !data.user_code) {
|
|
188
|
+
throw new Error('The server did not return a sign-in code. Please try again.');
|
|
189
|
+
}
|
|
190
|
+
const expiresInRaw = Number(data.expires_in);
|
|
191
|
+
const expiresIn = Number.isFinite(expiresInRaw) && expiresInRaw > 0 ? expiresInRaw : DEFAULT_EXPIRES_IN_S;
|
|
192
|
+
const pending = {
|
|
193
|
+
device_code: data.device_code,
|
|
194
|
+
user_code: data.user_code,
|
|
195
|
+
link: deviceLink(data.user_code, ref),
|
|
196
|
+
api_base: apiBase,
|
|
197
|
+
expires_at: new Date(now() + expiresIn * 1000).toISOString(),
|
|
198
|
+
interval: saneInterval(data.interval, DEFAULT_INTERVAL_S),
|
|
199
|
+
};
|
|
200
|
+
savePendingDeviceLogin(pending);
|
|
201
|
+
return pending;
|
|
202
|
+
}
|
|
203
|
+
/** Prints the link and code. Never opens a browser. */
|
|
204
|
+
function printDeviceInstructions(pending, opts = {}) {
|
|
205
|
+
const now = opts.now ?? Date.now;
|
|
206
|
+
const left = Date.parse(pending.expires_at) - now();
|
|
207
|
+
const heading = opts.resumed ? 'Still waiting for you to approve:' : 'Sign in to GooseWorks from any device:';
|
|
208
|
+
logger.info(`${heading}\n ${pending.link}`);
|
|
209
|
+
if (left > 0) {
|
|
210
|
+
const minutes = Math.max(1, Math.ceil(left / 60_000));
|
|
211
|
+
logger.info(`Code: ${pending.user_code} (expires in ${minutes} minute${minutes === 1 ? '' : 's'})`);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Past its approval deadline but inside the collection grace: the server
|
|
215
|
+
// still hands over the key if the user approved in time.
|
|
216
|
+
logger.info(`Code: ${pending.user_code}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const defaultSleep = (ms, signal) => new Promise((resolve) => {
|
|
220
|
+
const onAbort = () => { clearTimeout(timer); resolve(); };
|
|
221
|
+
const timer = setTimeout(() => {
|
|
222
|
+
signal?.removeEventListener('abort', onAbort);
|
|
223
|
+
resolve();
|
|
224
|
+
}, ms);
|
|
225
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
226
|
+
});
|
|
227
|
+
function credentialsFromPoll(apiBase, data) {
|
|
228
|
+
if (!data || typeof data.token !== 'string' || !data.token || typeof data.email !== 'string' || !data.email || typeof data.agent_id !== 'string' || !data.agent_id) {
|
|
229
|
+
throw new Error('The server sent an incomplete sign-in. Run the command again for a new link.');
|
|
230
|
+
}
|
|
231
|
+
const scopeType = data.scope_type === 'agent' || data.scope_type === 'user' ? data.scope_type : undefined;
|
|
232
|
+
return {
|
|
233
|
+
api_key: data.token,
|
|
234
|
+
email: data.email,
|
|
235
|
+
agent_id: data.agent_id,
|
|
236
|
+
api_base: data.api_base || apiBase,
|
|
237
|
+
...(scopeType ? { scope_type: scopeType } : {}),
|
|
238
|
+
...(data.default_agent_id ? { default_agent_id: data.default_agent_id } : {}),
|
|
239
|
+
...(data.mcp_server_url ? { mcp_server_url: data.mcp_server_url } : {}),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/** One poll. Saves the key on success; never throws for a server answer. */
|
|
243
|
+
async function pollOnce(apiBase, pending, interval, guard = (work) => work) {
|
|
244
|
+
let res;
|
|
245
|
+
try {
|
|
246
|
+
res = await guard((0, http_1.requestJson)({
|
|
247
|
+
apiBase: trimBase(apiBase),
|
|
248
|
+
method: 'POST',
|
|
249
|
+
path: '/api/cli/device/poll',
|
|
250
|
+
body: { device_code: pending.device_code },
|
|
251
|
+
timeoutMs: POLL_TIMEOUT_MS,
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
if (err instanceof DeviceLoginStoppedError)
|
|
256
|
+
throw err;
|
|
257
|
+
if (err instanceof http_1.HttpError && err.status === 404) {
|
|
258
|
+
clearPendingDeviceLogin();
|
|
259
|
+
return { kind: 'gone', message: exports.EXPIRED_MESSAGE };
|
|
260
|
+
}
|
|
261
|
+
if (err instanceof http_1.HttpError && err.status === 429) {
|
|
262
|
+
return { kind: 'waiting', interval: Math.min(interval + 2, MAX_INTERVAL_S) };
|
|
263
|
+
}
|
|
264
|
+
if (err instanceof http_1.HttpError && err.status >= 400 && err.status < 500) {
|
|
265
|
+
clearPendingDeviceLogin();
|
|
266
|
+
return { kind: 'gone', message: `Sign-in failed (status ${err.status}). Run the command again for a new link.` };
|
|
267
|
+
}
|
|
268
|
+
// 5xx, timeouts and network errors are transient.
|
|
269
|
+
return { kind: 'waiting', interval };
|
|
270
|
+
}
|
|
271
|
+
switch (res?.status) {
|
|
272
|
+
case 'success': {
|
|
273
|
+
// The code is single-use: once collected, the pending file is useless.
|
|
274
|
+
try {
|
|
275
|
+
const creds = credentialsFromPoll(apiBase, res.data);
|
|
276
|
+
if ((0, environment_1.getEnvironment)() === 'staging' && (!res.data?.api_base || new URL(res.data.api_base).origin !== new URL(apiBase).origin)) {
|
|
277
|
+
throw new Error('The sign-in did not confirm the staging API');
|
|
278
|
+
}
|
|
279
|
+
(0, credentials_1.validateCredentials)(creds);
|
|
280
|
+
(0, credentials_1.saveCredentials)(creds);
|
|
281
|
+
return {
|
|
282
|
+
kind: 'done',
|
|
283
|
+
result: {
|
|
284
|
+
api_key: creds.api_key,
|
|
285
|
+
email: creds.email,
|
|
286
|
+
agent_id: creds.agent_id,
|
|
287
|
+
...(creds.scope_type ? { scope_type: creds.scope_type } : {}),
|
|
288
|
+
...(creds.default_agent_id ? { default_agent_id: creds.default_agent_id } : {}),
|
|
289
|
+
...(creds.mcp_server_url ? { mcp_server_url: creds.mcp_server_url } : {}),
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
finally {
|
|
294
|
+
clearPendingDeviceLogin();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
case 'expired':
|
|
298
|
+
clearPendingDeviceLogin();
|
|
299
|
+
return { kind: 'gone', message: exports.EXPIRED_MESSAGE };
|
|
300
|
+
case 'denied':
|
|
301
|
+
clearPendingDeviceLogin();
|
|
302
|
+
return { kind: 'gone', message: exports.DENIED_MESSAGE };
|
|
303
|
+
case 'slow_down':
|
|
304
|
+
return { kind: 'waiting', interval: saneInterval(res.interval, Math.min(interval + 2, MAX_INTERVAL_S)) };
|
|
305
|
+
default:
|
|
306
|
+
// 'pending' (and anything unrecognised): keep the server's pace.
|
|
307
|
+
return { kind: 'waiting', interval: saneInterval(res?.interval, interval) };
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Polls until the user approves, denies, or the code expires. On success the
|
|
312
|
+
* key is saved like a browser sign-in and the pending file is removed. The
|
|
313
|
+
* server decides expiry; the local cut-off (expiry plus the approval grace)
|
|
314
|
+
* only stops a server that never answers.
|
|
315
|
+
*/
|
|
316
|
+
async function waitForDeviceLogin(apiBase, pending, deps = {}) {
|
|
317
|
+
const sleep = deps.sleep ?? defaultSleep;
|
|
318
|
+
const now = deps.now ?? Date.now;
|
|
319
|
+
const giveUpAt = Date.parse(pending.expires_at) + exports.APPROVAL_GRACE_MS;
|
|
320
|
+
let interval = saneInterval(pending.interval, DEFAULT_INTERVAL_S);
|
|
321
|
+
const controller = new AbortController();
|
|
322
|
+
const stopped = new Promise((_, reject) => {
|
|
323
|
+
controller.signal.addEventListener('abort', () => reject(new DeviceLoginStoppedError()), { once: true });
|
|
324
|
+
});
|
|
325
|
+
stopped.catch(() => undefined);
|
|
326
|
+
const guard = (work) => Promise.race([work, stopped]);
|
|
327
|
+
const onSignal = () => controller.abort();
|
|
328
|
+
process.once('SIGINT', onSignal);
|
|
329
|
+
process.once('SIGTERM', onSignal);
|
|
330
|
+
try {
|
|
331
|
+
for (;;) {
|
|
332
|
+
const step = await pollOnce(apiBase, pending, interval, guard);
|
|
333
|
+
if (step.kind === 'done')
|
|
334
|
+
return step.result;
|
|
335
|
+
if (step.kind === 'gone')
|
|
336
|
+
throw new Error(step.message);
|
|
337
|
+
interval = step.interval;
|
|
338
|
+
if (!(now() < giveUpAt)) {
|
|
339
|
+
clearPendingDeviceLogin();
|
|
340
|
+
throw new Error(exports.EXPIRED_MESSAGE);
|
|
341
|
+
}
|
|
342
|
+
await guard(sleep(interval * 1000, controller.signal));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
finally {
|
|
346
|
+
process.removeListener('SIGINT', onSignal);
|
|
347
|
+
process.removeListener('SIGTERM', onSignal);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Resume a saved request for this API base, or start a new one; print the
|
|
352
|
+
* link; then either return at once (`wait: false`) or wait for approval.
|
|
353
|
+
* Resuming with `wait: false` asks the server first, so it never re-prints a
|
|
354
|
+
* code that was already approved, canceled or used.
|
|
355
|
+
*/
|
|
356
|
+
async function runDeviceFlow(apiBase, opts = {}) {
|
|
357
|
+
const now = opts.now ?? Date.now;
|
|
358
|
+
let existing = readPendingDeviceLogin(apiBase, now);
|
|
359
|
+
if (existing && opts.wait === false) {
|
|
360
|
+
const step = await pollOnce(apiBase, existing, existing.interval);
|
|
361
|
+
if (step.kind === 'done')
|
|
362
|
+
return { status: 'done', result: step.result };
|
|
363
|
+
if (step.kind === 'gone')
|
|
364
|
+
existing = null;
|
|
365
|
+
}
|
|
366
|
+
const pending = existing ?? await startDeviceLogin(apiBase, opts.ref, now, opts.sleep);
|
|
367
|
+
printDeviceInstructions(pending, { resumed: existing !== null, now });
|
|
368
|
+
if (opts.wait === false)
|
|
369
|
+
return { status: 'pending', pending };
|
|
370
|
+
const result = await waitForDeviceLogin(apiBase, pending, { sleep: opts.sleep, now });
|
|
371
|
+
return { status: 'done', result };
|
|
372
|
+
}
|
|
373
|
+
//# 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
|
-
|
|
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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-server.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-server.ts"],"names":[],"mappings":"AAWA,
|
|
1
|
+
{"version":3,"file":"oauth-server.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-server.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,gBAAgB,SAAU,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,WAAW,CAAC,CAmJtB"}
|