codiedev 0.9.79 → 0.9.81
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/assets/opencode-plugin.mjs +6 -0
- package/assets/session-key.mjs +48 -0
- package/dist/cli.js +113 -9
- package/dist/cliSession.d.ts +108 -0
- package/dist/cliSession.js +513 -0
- package/dist/codie.js +21 -1
- package/dist/commands/agentTemplates.generated.d.ts +11 -0
- package/dist/commands/agentTemplates.generated.js +139 -0
- package/dist/commands/agents.d.ts +7 -0
- package/dist/commands/agents.js +1130 -0
- package/dist/commands/agentsSdk.generated.d.ts +4 -0
- package/dist/commands/agentsSdk.generated.js +10 -0
- package/dist/commands/scrub.d.ts +11 -0
- package/dist/commands/scrub.js +102 -0
- package/dist/configDir.d.ts +9 -0
- package/dist/configDir.js +25 -1
- package/dist/connect.js +45 -2
- package/dist/connectFlow.d.ts +21 -0
- package/dist/connectFlow.js +41 -0
- package/dist/hook.js +25 -0
- package/dist/knownSecrets.d.ts +43 -0
- package/dist/knownSecrets.js +241 -0
- package/dist/launcher.d.ts +7 -2
- package/dist/launcher.js +36 -2
- package/dist/localScrub.d.ts +172 -0
- package/dist/localScrub.js +820 -0
- package/dist/localScrubReport.d.ts +83 -0
- package/dist/localScrubReport.js +268 -0
- package/dist/managedPi.js +18 -2
- package/dist/mcp.js +3 -0
- package/dist/scrub/extraRules.d.ts +4 -0
- package/dist/scrub/extraRules.js +17 -0
- package/dist/scrub/rules.d.ts +86 -0
- package/dist/scrub/rules.js +645 -0
- package/dist/scrub/scrubProviderRules.d.ts +14 -0
- package/dist/scrub/scrubProviderRules.js +149 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +9 -7
- package/package.json +5 -4
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
trackWorkPath,
|
|
11
11
|
workDirBySession,
|
|
12
12
|
} from "./git-refs.mjs";
|
|
13
|
+
import { freshGatewayKey } from "./session-key.mjs";
|
|
13
14
|
|
|
14
15
|
const skillUseBySession = new Map();
|
|
15
16
|
|
|
@@ -60,6 +61,11 @@ export const CodiedevMetadata = async () => ({
|
|
|
60
61
|
});
|
|
61
62
|
},
|
|
62
63
|
"chat.headers": async (input, output) => {
|
|
64
|
+
// Browser sign-in: the current 24h token, refreshed as it nears expiry,
|
|
65
|
+
// so a session open for days keeps working (see session-key.mjs). Exact
|
|
66
|
+
// "Authorization" key: per-call headers win over the apiKey-derived one.
|
|
67
|
+
const key = await freshGatewayKey();
|
|
68
|
+
if (key) output.headers.Authorization = `Bearer ${key}`;
|
|
63
69
|
Object.assign(
|
|
64
70
|
output.headers,
|
|
65
71
|
buildAttributionHeaders({
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// The gateway key for one model request, kept fresh for the whole session.
|
|
2
|
+
//
|
|
3
|
+
// With browser sign-in (`codiedev connect`), the key is a 24h access token.
|
|
4
|
+
// The engine (OpenCode, pi) would otherwise hold the one it was launched
|
|
5
|
+
// with until the session ends, so a session open for more than a day would
|
|
6
|
+
// start failing. `codie` sets these variables only for a browser sign-in:
|
|
7
|
+
// CODIEDEV_SESSION_CONFIG path to ~/.codiedev/config.json
|
|
8
|
+
// CODIEDEV_CLI_JS the CLI entry (dist/cli.js)
|
|
9
|
+
// CODIEDEV_NODE the node binary that runs it
|
|
10
|
+
// Each request reads the current token from config (other codiedev
|
|
11
|
+
// processes may have refreshed it). When it has under 30 minutes left, this
|
|
12
|
+
// runs `codiedev session-refresh`, which refreshes under the shared lock
|
|
13
|
+
// (cliSession.ts, specs/tla/CliSession.tla), then reads again.
|
|
14
|
+
// No variables (pasted API token, CI): returns null and the launch key stands.
|
|
15
|
+
|
|
16
|
+
import { execFile } from "node:child_process";
|
|
17
|
+
import { readFileSync } from "node:fs";
|
|
18
|
+
|
|
19
|
+
export const REFRESH_WHEN_LEFT_MS = 30 * 60_000;
|
|
20
|
+
|
|
21
|
+
function readSession(path) {
|
|
22
|
+
try {
|
|
23
|
+
const c = JSON.parse(readFileSync(path, "utf8"));
|
|
24
|
+
return c && c.auth && typeof c.token === "string" && c.token ? c : null;
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function runRefresh(env) {
|
|
31
|
+
return new Promise((resolve) => {
|
|
32
|
+
execFile(env.CODIEDEV_NODE, [env.CODIEDEV_CLI_JS, "session-refresh"], { timeout: 30_000, env }, () => resolve());
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Fresh gateway key, or null when the session isn't a browser sign-in. */
|
|
37
|
+
export async function freshGatewayKey(env = process.env, now = Date.now, refresh = runRefresh) {
|
|
38
|
+
const path = env.CODIEDEV_SESSION_CONFIG;
|
|
39
|
+
if (!path || !env.CODIEDEV_CLI_JS || !env.CODIEDEV_NODE) return null;
|
|
40
|
+
let session = readSession(path);
|
|
41
|
+
if (!session) return null;
|
|
42
|
+
const left = Number(session.auth.accessTokenExpiresAt) - now();
|
|
43
|
+
if (!(left > REFRESH_WHEN_LEFT_MS)) {
|
|
44
|
+
await refresh(env);
|
|
45
|
+
session = readSession(path) ?? session;
|
|
46
|
+
}
|
|
47
|
+
return session.token;
|
|
48
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -13,8 +13,43 @@
|
|
|
13
13
|
* codiedev note "<text>" — capture a thought
|
|
14
14
|
* codiedev help — show this help
|
|
15
15
|
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
16
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
50
|
const connect_1 = require("./connect");
|
|
51
|
+
const cliSession_1 = require("./cliSession");
|
|
52
|
+
const utils_1 = require("./utils");
|
|
18
53
|
const push_1 = require("./commands/push");
|
|
19
54
|
const delete_1 = require("./commands/delete");
|
|
20
55
|
const pull_1 = require("./commands/pull");
|
|
@@ -32,6 +67,7 @@ const capture_1 = require("./commands/capture");
|
|
|
32
67
|
const pack_1 = require("./commands/pack");
|
|
33
68
|
const traces_1 = require("./commands/traces");
|
|
34
69
|
const evals_1 = require("./commands/evals");
|
|
70
|
+
const agents_1 = require("./commands/agents");
|
|
35
71
|
// --- starter packs phase 2 ---
|
|
36
72
|
const hookGate_1 = require("./packs/hookGate");
|
|
37
73
|
const sync_1 = require("./packs/sync");
|
|
@@ -45,8 +81,10 @@ Codiedev CLI
|
|
|
45
81
|
someone left off across sessions and providers.
|
|
46
82
|
|
|
47
83
|
Connect:
|
|
48
|
-
codiedev connect
|
|
84
|
+
codiedev connect Sign in with your browser and link
|
|
85
|
+
Claude Code / Codex / Cursor /
|
|
49
86
|
GitHub Copilot / pi to your org
|
|
87
|
+
codiedev logout Sign this machine out
|
|
50
88
|
codiedev doctor Verify your setup after connecting
|
|
51
89
|
|
|
52
90
|
Harness:
|
|
@@ -94,6 +132,9 @@ Starter packs:
|
|
|
94
132
|
codiedev pack status Installed packs, up to date or not
|
|
95
133
|
|
|
96
134
|
Traces (agents on the gateway):
|
|
135
|
+
codiedev agents init | deploy | run | runs | show | secrets | webhook
|
|
136
|
+
Deploy agents and run them in fresh sandboxes
|
|
137
|
+
(codiedev agents help)
|
|
97
138
|
codiedev traces agents Agents you maintain, with saved test cases
|
|
98
139
|
codiedev traces cases <agent> [--dataset name [--version n]] [--model id]
|
|
99
140
|
Pull an agent's test cases (or one dataset)
|
|
@@ -117,6 +158,7 @@ Privacy:
|
|
|
117
158
|
codiedev ignore <path> Never capture this folder or its children
|
|
118
159
|
codiedev unignore <path> Stop ignoring a folder
|
|
119
160
|
codiedev ignored [path] List ignored folders, or check one path
|
|
161
|
+
codiedev scrub [--dry-run] Remove keys from past agent sessions on this machine
|
|
120
162
|
|
|
121
163
|
Capture:
|
|
122
164
|
codiedev note "<text>" Capture a passing thought
|
|
@@ -168,12 +210,14 @@ status sync never weakens it.
|
|
|
168
210
|
const COMMAND_HELP = {
|
|
169
211
|
pack: pack_1.PACK_HELP,
|
|
170
212
|
traces: traces_1.TRACES_HELP,
|
|
213
|
+
agents: agents_1.AGENTS_HELP,
|
|
171
214
|
evals: evals_1.EVALS_HELP,
|
|
172
215
|
connect: `
|
|
173
216
|
codiedev connect — link your agent CLI to Codiedev
|
|
174
217
|
|
|
175
|
-
|
|
176
|
-
|
|
218
|
+
Opens your browser to sign in (approve once, no API key to copy), then
|
|
219
|
+
installs:
|
|
220
|
+
- ~/.codiedev/config.json (sign-in + org + tracked repos)
|
|
177
221
|
- ~/.claude/settings.json hook (captures session transcripts)
|
|
178
222
|
- ~/.claude/CLAUDE.md instructions (teaches Claude the commands)
|
|
179
223
|
- ~/.codex/hooks.json hook (same, for Codex)
|
|
@@ -186,7 +230,27 @@ codiedev connect — link your agent CLI to Codiedev
|
|
|
186
230
|
|
|
187
231
|
Re-run anytime to swap accounts or refresh the instruction block.
|
|
188
232
|
|
|
189
|
-
|
|
233
|
+
Over SSH or on a machine with no display it shows a link and a short code
|
|
234
|
+
instead: open the link on your laptop or phone, check the code, approve.
|
|
235
|
+
Detected automatically.
|
|
236
|
+
|
|
237
|
+
Options:
|
|
238
|
+
--token Paste an API token instead of signing in with a browser
|
|
239
|
+
(CI, or a machine with no browser anywhere). Create one at
|
|
240
|
+
https://codiedev.com/portal/integrations/claude-code
|
|
241
|
+
--force, -f Sign in again even if this machine is already connected.
|
|
242
|
+
|
|
243
|
+
Browser sign-in stores a 24-hour access token and a refresh token that
|
|
244
|
+
rotates on every use; nothing long-lived is saved. Revoke a machine from
|
|
245
|
+
Integrations in the portal, or run 'codiedev logout' on it.
|
|
246
|
+
`.trim(),
|
|
247
|
+
logout: `
|
|
248
|
+
codiedev logout — sign this machine out
|
|
249
|
+
|
|
250
|
+
Ends this machine's browser sign-in on the server and removes it from
|
|
251
|
+
~/.codiedev/config.json. Device settings (ignored folders) are kept.
|
|
252
|
+
For a pasted API token, it's only forgotten locally: revoke it in the
|
|
253
|
+
portal under Integrations.
|
|
190
254
|
`.trim(),
|
|
191
255
|
push: `
|
|
192
256
|
codiedev push — author or update an artifact
|
|
@@ -405,13 +469,15 @@ Run 'codiedev help <command>' for each, or see the quick list:
|
|
|
405
469
|
|
|
406
470
|
codiedev help
|
|
407
471
|
|
|
408
|
-
##
|
|
472
|
+
## Signing in
|
|
409
473
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
3. Copy the cdv_... string and paste it into 'codiedev connect'
|
|
474
|
+
'codiedev connect' opens your browser; approve, and you're done. Nothing
|
|
475
|
+
long-lived is stored: a 24-hour access token plus a rotating refresh token.
|
|
413
476
|
|
|
414
|
-
|
|
477
|
+
Over SSH it shows a link and code to approve from your laptop or phone,
|
|
478
|
+
automatically. For CI, create a token at
|
|
479
|
+
https://codiedev.com/portal/integrations/claude-code and run
|
|
480
|
+
'codiedev connect --token'.
|
|
415
481
|
`.trim();
|
|
416
482
|
// Retired commands: say so instead of "Unknown command", since agent
|
|
417
483
|
// instructions written by older installs may still reference them.
|
|
@@ -474,11 +540,41 @@ async function main() {
|
|
|
474
540
|
console.log(`codiedev v${version_1.CLI_VERSION}`);
|
|
475
541
|
return;
|
|
476
542
|
}
|
|
543
|
+
// Browser sign-in: refresh the access token (under the shared lock) before
|
|
544
|
+
// the command reads config. No-op for pasted API tokens.
|
|
545
|
+
if (command !== "connect" && command !== "logout") {
|
|
546
|
+
const fresh = await (0, cliSession_1.ensureFreshToken)({ configPath: utils_1.CONFIG_PATH }).catch(() => null);
|
|
547
|
+
if (fresh?.status === "signed_out") {
|
|
548
|
+
console.error("\nYour Codiedev sign-in has ended (revoked or expired). Run `codiedev connect` to sign in again.\n");
|
|
549
|
+
}
|
|
550
|
+
}
|
|
477
551
|
try {
|
|
478
552
|
switch (command) {
|
|
479
553
|
case "connect":
|
|
480
554
|
await (0, connect_1.runConnect)(rest);
|
|
481
555
|
return;
|
|
556
|
+
case "session-refresh": {
|
|
557
|
+
// Internal: the Codie engine's per-request hook asks for a fresh
|
|
558
|
+
// token when the current one has under 30 minutes left. Refreshes
|
|
559
|
+
// under the shared lock; prints nothing.
|
|
560
|
+
await (0, cliSession_1.ensureFreshToken)({ configPath: utils_1.CONFIG_PATH }, 60 * 60_000).catch(() => null);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
case "logout": {
|
|
564
|
+
const out = await (0, cliSession_1.logout)({ configPath: utils_1.CONFIG_PATH });
|
|
565
|
+
if (!out.wasConnected) {
|
|
566
|
+
console.log("This machine isn't signed in.");
|
|
567
|
+
}
|
|
568
|
+
else if (out.hadBrowserAuth) {
|
|
569
|
+
console.log(out.serverRevoked
|
|
570
|
+
? "Signed out. This machine's sign-in is revoked."
|
|
571
|
+
: "Signed out on this machine. Couldn't reach Codiedev to revoke the sign-in; revoke it under Integrations in the portal.");
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
console.log("Removed the API token from this machine. It still works elsewhere until you revoke it under Integrations in the portal.");
|
|
575
|
+
}
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
482
578
|
case "doctor":
|
|
483
579
|
case "verify":
|
|
484
580
|
await (0, doctor_1.runDoctor)(rest);
|
|
@@ -512,9 +608,17 @@ async function main() {
|
|
|
512
608
|
case "read":
|
|
513
609
|
await (0, inbox_1.runRead)(rest);
|
|
514
610
|
return;
|
|
611
|
+
case "scrub": {
|
|
612
|
+
const { runScrubCommand } = await Promise.resolve().then(() => __importStar(require("./commands/scrub")));
|
|
613
|
+
process.exitCode = await runScrubCommand(rest);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
515
616
|
case "note":
|
|
516
617
|
await (0, note_1.runNote)(rest);
|
|
517
618
|
return;
|
|
619
|
+
case "agents":
|
|
620
|
+
await (0, agents_1.runAgents)(rest);
|
|
621
|
+
return;
|
|
518
622
|
case "promote":
|
|
519
623
|
case "reverse-ticket":
|
|
520
624
|
case "reverseTicket":
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { CodiedevConfig } from "./utils";
|
|
2
|
+
export interface BrowserAuth {
|
|
3
|
+
kind: "browser";
|
|
4
|
+
clientId: string;
|
|
5
|
+
refreshToken: string;
|
|
6
|
+
/** epoch ms when `token` (the access token) stops working */
|
|
7
|
+
accessTokenExpiresAt: number;
|
|
8
|
+
}
|
|
9
|
+
export interface TokenSet {
|
|
10
|
+
accessToken: string;
|
|
11
|
+
refreshToken: string;
|
|
12
|
+
expiresAt: number;
|
|
13
|
+
clientId: string;
|
|
14
|
+
}
|
|
15
|
+
/** Default: refresh when less than 10 minutes remain. */
|
|
16
|
+
export declare const DEFAULT_MIN_VALIDITY_MS: number;
|
|
17
|
+
/** A lock older than this was left by a crashed process. Refresh calls time
|
|
18
|
+
* out well before it (REFRESH_TIMEOUT_MS), so a live holder never looks stale. */
|
|
19
|
+
export declare const LOCK_STALE_MS = 30000;
|
|
20
|
+
export interface SessionDeps {
|
|
21
|
+
configPath: string;
|
|
22
|
+
fetchImpl?: typeof fetch;
|
|
23
|
+
now?: () => number;
|
|
24
|
+
sleep?: (ms: number) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function readConfigAt(configPath: string): CodiedevConfig | null;
|
|
27
|
+
/** rename(), retrying the transient Windows sharing errors. Exported for tests. */
|
|
28
|
+
export declare function renameWithRetry(from: string, to: string, rename?: (a: string, b: string) => void, sleep?: (ms: number) => void): void;
|
|
29
|
+
/**
|
|
30
|
+
* Write via temp file + rename so a concurrent reader never sees a torn file.
|
|
31
|
+
* If the rename still fails after ~1.6s of retries (a handle held that long),
|
|
32
|
+
* fall back to writing in place: a rare torn read beats failing `connect`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function writeConfigAtomic(configPath: string, config: CodiedevConfig): void;
|
|
35
|
+
export type FreshResult = {
|
|
36
|
+
status: "fresh";
|
|
37
|
+
config: CodiedevConfig;
|
|
38
|
+
} | {
|
|
39
|
+
status: "refreshed";
|
|
40
|
+
config: CodiedevConfig;
|
|
41
|
+
} | {
|
|
42
|
+
status: "adopted";
|
|
43
|
+
config: CodiedevConfig;
|
|
44
|
+
} | {
|
|
45
|
+
status: "unavailable";
|
|
46
|
+
config: CodiedevConfig;
|
|
47
|
+
} | {
|
|
48
|
+
status: "signed_out";
|
|
49
|
+
config: CodiedevConfig;
|
|
50
|
+
} | {
|
|
51
|
+
status: "none";
|
|
52
|
+
config: CodiedevConfig | null;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Make sure config.token is a usable access token for at least
|
|
56
|
+
* `minValidityMs`. Never throws: auth problems surface as the next request's
|
|
57
|
+
* 401, which every command already explains.
|
|
58
|
+
*/
|
|
59
|
+
export declare function ensureFreshToken(deps: SessionDeps, minValidityMs?: number): Promise<FreshResult>;
|
|
60
|
+
export declare function pkcePair(): {
|
|
61
|
+
verifier: string;
|
|
62
|
+
challenge: string;
|
|
63
|
+
};
|
|
64
|
+
export declare function openBrowser(url: string): boolean;
|
|
65
|
+
export interface LoginOptions {
|
|
66
|
+
backendUrl: string;
|
|
67
|
+
clientName?: string;
|
|
68
|
+
fetchImpl?: typeof fetch;
|
|
69
|
+
/** Test hook: called with the authorize URL instead of opening a browser. */
|
|
70
|
+
onAuthorizeUrl?: (url: string) => void;
|
|
71
|
+
log?: (line: string) => void;
|
|
72
|
+
now?: () => number;
|
|
73
|
+
}
|
|
74
|
+
/** Parse `code`/`state` (or `error`) out of a loopback callback URL. */
|
|
75
|
+
export declare function parseCallback(input: string): {
|
|
76
|
+
code?: string;
|
|
77
|
+
state?: string;
|
|
78
|
+
error?: string;
|
|
79
|
+
};
|
|
80
|
+
export declare function browserLogin(opts: LoginOptions): Promise<TokenSet>;
|
|
81
|
+
export declare const DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
82
|
+
/**
|
|
83
|
+
* True when a browser opened here can't reach the user: an SSH session, or a
|
|
84
|
+
* Linux box with no display. Then `connect` uses the device flow (a code the
|
|
85
|
+
* user approves on any device) instead of a loopback redirect, with no flag.
|
|
86
|
+
*/
|
|
87
|
+
export declare function isHeadless(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
|
|
88
|
+
export interface DeviceLoginOptions {
|
|
89
|
+
backendUrl: string;
|
|
90
|
+
clientName?: string;
|
|
91
|
+
fetchImpl?: typeof fetch;
|
|
92
|
+
log?: (line: string) => void;
|
|
93
|
+
now?: () => number;
|
|
94
|
+
sleep?: (ms: number) => Promise<void>;
|
|
95
|
+
/** Test hook: receives the code + link instead of only printing them. */
|
|
96
|
+
onCode?: (info: {
|
|
97
|
+
userCode: string;
|
|
98
|
+
verificationUri: string;
|
|
99
|
+
verificationUriComplete: string;
|
|
100
|
+
}) => void;
|
|
101
|
+
}
|
|
102
|
+
export declare function deviceLogin(opts: DeviceLoginOptions): Promise<TokenSet>;
|
|
103
|
+
/** `codiedev logout`: end a browser sign-in server-side, forget it locally. */
|
|
104
|
+
export declare function logout(deps: SessionDeps): Promise<{
|
|
105
|
+
wasConnected: boolean;
|
|
106
|
+
hadBrowserAuth: boolean;
|
|
107
|
+
serverRevoked: boolean;
|
|
108
|
+
}>;
|