browse 0.11.0 → 0.11.1
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.
|
@@ -59,24 +59,6 @@ export async function readDevToolsActivePort(userDataDir) {
|
|
|
59
59
|
return null;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
function isPortReachable(port, timeoutMs = 500) {
|
|
63
|
-
return new Promise((resolve) => {
|
|
64
|
-
const socket = net.createConnection({ host: "127.0.0.1", port });
|
|
65
|
-
const timer = setTimeout(() => {
|
|
66
|
-
socket.destroy();
|
|
67
|
-
resolve(false);
|
|
68
|
-
}, timeoutMs);
|
|
69
|
-
socket.on("connect", () => {
|
|
70
|
-
clearTimeout(timer);
|
|
71
|
-
socket.destroy();
|
|
72
|
-
resolve(true);
|
|
73
|
-
});
|
|
74
|
-
socket.on("error", () => {
|
|
75
|
-
clearTimeout(timer);
|
|
76
|
-
resolve(false);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
62
|
async function probeJsonVersion(port) {
|
|
81
63
|
const controller = new AbortController();
|
|
82
64
|
const timer = setTimeout(() => controller.abort(), 2000);
|
|
@@ -97,6 +79,46 @@ async function probeJsonVersion(port) {
|
|
|
97
79
|
clearTimeout(timer);
|
|
98
80
|
}
|
|
99
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Multiple candidates (several profile dirs, or a profile dir and a fallback
|
|
84
|
+
* port) can reference the same port within one discovery call. Memoize the
|
|
85
|
+
* live /json/version probe per port so that port is only actually hit once.
|
|
86
|
+
*/
|
|
87
|
+
function createJsonVersionProbe() {
|
|
88
|
+
const cache = new Map();
|
|
89
|
+
return (port) => {
|
|
90
|
+
let pending = cache.get(port);
|
|
91
|
+
if (!pending) {
|
|
92
|
+
pending = probeJsonVersion(port);
|
|
93
|
+
cache.set(port, pending);
|
|
94
|
+
}
|
|
95
|
+
return pending;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function wsPathname(wsUrl) {
|
|
99
|
+
try {
|
|
100
|
+
return new URL(wsUrl).pathname;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A DevToolsActivePort file only reflects the browser instance that wrote it.
|
|
108
|
+
* If a different process later binds the same port (a very likely collision,
|
|
109
|
+
* since 9222 is the near-universal default debugging port), the cached
|
|
110
|
+
* port+wsPath pair points at a target that no longer exists. Confirm the
|
|
111
|
+
* port's live /json/version still reports this exact target before trusting
|
|
112
|
+
* it. Compare pathnames only (not the full URL) since Chrome can report the
|
|
113
|
+
* host as "127.0.0.1" or "localhost" depending on version/platform.
|
|
114
|
+
*/
|
|
115
|
+
async function isDevToolsActivePortFresh(info, probe = probeJsonVersion) {
|
|
116
|
+
const liveWsUrl = await probe(info.port);
|
|
117
|
+
if (!liveWsUrl)
|
|
118
|
+
return false;
|
|
119
|
+
const expectedPathname = wsPathname(buildDevToolsWsUrl(info.port, info.wsPath));
|
|
120
|
+
return (expectedPathname !== null && wsPathname(liveWsUrl) === expectedPathname);
|
|
121
|
+
}
|
|
100
122
|
async function verifyCdpWebSocket(wsUrl) {
|
|
101
123
|
return new Promise((resolve) => {
|
|
102
124
|
const url = new URL(wsUrl);
|
|
@@ -135,12 +157,12 @@ async function verifyCdpWebSocket(wsUrl) {
|
|
|
135
157
|
});
|
|
136
158
|
});
|
|
137
159
|
}
|
|
138
|
-
async function resolveDevToolsActivePortUrl(port, userDataDirs) {
|
|
160
|
+
async function resolveDevToolsActivePortUrl(port, userDataDirs, probe) {
|
|
139
161
|
for (const dir of userDataDirs) {
|
|
140
162
|
const info = await readDevToolsActivePort(dir);
|
|
141
163
|
if (!info || info.port !== port)
|
|
142
164
|
continue;
|
|
143
|
-
if (!(await
|
|
165
|
+
if (!(await isDevToolsActivePortFresh(info, probe)))
|
|
144
166
|
continue;
|
|
145
167
|
return buildDevToolsWsUrl(info.port, info.wsPath);
|
|
146
168
|
}
|
|
@@ -148,10 +170,11 @@ async function resolveDevToolsActivePortUrl(port, userDataDirs) {
|
|
|
148
170
|
}
|
|
149
171
|
export async function resolveWsTargetFromPort(port, options = {}) {
|
|
150
172
|
const userDataDirs = options.userDataDirs ?? getChromeUserDataDirs();
|
|
151
|
-
const
|
|
173
|
+
const probe = createJsonVersionProbe();
|
|
174
|
+
const devToolsUrl = await resolveDevToolsActivePortUrl(port, userDataDirs, probe);
|
|
152
175
|
if (devToolsUrl)
|
|
153
176
|
return devToolsUrl;
|
|
154
|
-
const jsonVersionUrl = await
|
|
177
|
+
const jsonVersionUrl = await probe(port);
|
|
155
178
|
if (jsonVersionUrl)
|
|
156
179
|
return jsonVersionUrl;
|
|
157
180
|
const fallback = buildDevToolsWsUrl(port, "/devtools/browser");
|
|
@@ -162,9 +185,10 @@ export async function resolveWsTargetFromPort(port, options = {}) {
|
|
|
162
185
|
export async function discoverLocalCdp(options = {}) {
|
|
163
186
|
const candidates = [];
|
|
164
187
|
const userDataDirs = options.userDataDirs ?? getChromeUserDataDirs();
|
|
188
|
+
const probe = createJsonVersionProbe();
|
|
165
189
|
for (const dir of userDataDirs) {
|
|
166
190
|
const info = await readDevToolsActivePort(dir);
|
|
167
|
-
if (!info || !(await
|
|
191
|
+
if (!info || !(await isDevToolsActivePortFresh(info, probe)))
|
|
168
192
|
continue;
|
|
169
193
|
candidates.push({
|
|
170
194
|
source: `DevToolsActivePort:${dir}`,
|
|
@@ -172,7 +196,7 @@ export async function discoverLocalCdp(options = {}) {
|
|
|
172
196
|
});
|
|
173
197
|
}
|
|
174
198
|
for (const port of options.fallbackPorts ?? DEFAULT_FALLBACK_PORTS) {
|
|
175
|
-
const wsUrl = await
|
|
199
|
+
const wsUrl = await probe(port);
|
|
176
200
|
if (!wsUrl)
|
|
177
201
|
continue;
|
|
178
202
|
if (!candidates.some((candidate) => candidate.wsUrl === wsUrl)) {
|
|
@@ -377,7 +377,9 @@ async function routeRequest(request, response, bridge, manifestStore, sessionMan
|
|
|
377
377
|
? body.params || {}
|
|
378
378
|
: {};
|
|
379
379
|
const session = await sessionManager.createSession(manifest.config?.sessionConfig);
|
|
380
|
-
const accepted = bridge.triggerInvocation(functionName, params,
|
|
380
|
+
const accepted = bridge.triggerInvocation(functionName, params,
|
|
381
|
+
// Match production, which always sends secrets.
|
|
382
|
+
{ session, secrets: {} }, corsHeaders, response);
|
|
381
383
|
if (!accepted) {
|
|
382
384
|
await sessionManager.closeSession(session.id);
|
|
383
385
|
sendJson(response, 503, { error: "No runtime is connected yet." }, corsHeaders);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { fail } from "../errors.js";
|
|
@@ -17,24 +17,49 @@ dist/
|
|
|
17
17
|
.DS_Store
|
|
18
18
|
`;
|
|
19
19
|
const starterFunctionTemplate = `import { defineFn } from "@browserbasehq/sdk-functions";
|
|
20
|
-
import {
|
|
20
|
+
import { browserbase, Stagehand } from "@browserbasehq/stagehand";
|
|
21
|
+
import { z } from "zod/v4";
|
|
21
22
|
|
|
22
|
-
defineFn(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
defineFn(
|
|
24
|
+
"my-function",
|
|
25
|
+
async (context) => {
|
|
26
|
+
const browser = await browserbase.connect({
|
|
27
|
+
// The local dev server has no secrets, so fall back to .env.
|
|
28
|
+
apiKey:
|
|
29
|
+
context.secrets.BROWSERBASE_API_KEY ?? process.env.BROWSERBASE_API_KEY!,
|
|
30
|
+
sessionId: context.session.id,
|
|
31
|
+
});
|
|
32
|
+
// In this example, Stagehand uses the Model Gateway where Browserbase charges for the tokens
|
|
33
|
+
const stagehand = await Stagehand.create({ browser });
|
|
34
|
+
const page = (await browser.context.activePage())!;
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
await page.goto("https://news.ycombinator.com");
|
|
37
|
+
const { data } = await stagehand.extract(
|
|
38
|
+
"Extract the top 3 stories with their rank, title, and link URL.",
|
|
39
|
+
z.object({
|
|
40
|
+
stories: z
|
|
41
|
+
.array(z.object({ rank: z.number(), title: z.string(), url: z.string() }))
|
|
42
|
+
.max(3),
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
await stagehand.close();
|
|
47
|
+
return {
|
|
48
|
+
message: "Successfully fetched top Hacker News stories",
|
|
49
|
+
timestamp: new Date().toISOString(),
|
|
50
|
+
results: data.stories,
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
// Upload the Stagehand extension once, then paste its ID here:
|
|
55
|
+
// browse cloud extensions upload node_modules/@browserbasehq/stagehand/dist/assets/stagehand-extension.zip
|
|
56
|
+
sessionConfig: { extensionId: "your-extension-id" },
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
`;
|
|
60
|
+
// pnpm 11 and later fail installs when esbuild's build script is not approved.
|
|
61
|
+
const pnpmWorkspaceTemplate = `allowBuilds:
|
|
62
|
+
esbuild: true
|
|
38
63
|
`;
|
|
39
64
|
const tsconfigTemplate = `{
|
|
40
65
|
"compilerOptions": {
|
|
@@ -71,9 +96,15 @@ export async function initFunctionsProject({ packageManager, projectName, }) {
|
|
|
71
96
|
await writeFile(join(projectRoot, ".gitignore"), gitignoreTemplate);
|
|
72
97
|
await writeFile(join(projectRoot, "index.ts"), starterFunctionTemplate);
|
|
73
98
|
await writeFile(join(projectRoot, "tsconfig.json"), tsconfigTemplate);
|
|
99
|
+
if (packageManager === "pnpm") {
|
|
100
|
+
await writeFile(join(projectRoot, "pnpm-workspace.yaml"), pnpmWorkspaceTemplate);
|
|
101
|
+
}
|
|
74
102
|
const install = packageManager === "pnpm" ? ["add"] : ["install"];
|
|
75
103
|
const installDev = packageManager === "pnpm" ? ["add", "-D"] : ["install", "--save-dev"];
|
|
76
|
-
runPackageManager(packageManager, [...install, "@browserbasehq/sdk-functions", "
|
|
104
|
+
runPackageManager(packageManager, [...install, "@browserbasehq/sdk-functions", "@browserbasehq/stagehand"], projectRoot);
|
|
105
|
+
// Match Stagehand's version of zod in order to pass type checks.
|
|
106
|
+
const zodVersion = readStagehandZodVersion(projectRoot);
|
|
107
|
+
runPackageManager(packageManager, [...install, zodVersion ? `zod@${zodVersion}` : "zod"], projectRoot);
|
|
77
108
|
runPackageManager(packageManager, [...installDev, "typescript", "@types/node"], projectRoot);
|
|
78
109
|
if (!existsSync(join(projectRoot, ".git"))) {
|
|
79
110
|
spawnSync("git", ["init"], {
|
|
@@ -88,8 +119,11 @@ export async function initFunctionsProject({ packageManager, projectName, }) {
|
|
|
88
119
|
nextSteps: [
|
|
89
120
|
`cd ${projectName}`,
|
|
90
121
|
"Edit .env with your Browserbase API key",
|
|
91
|
-
|
|
92
|
-
|
|
122
|
+
"browse cloud extensions upload node_modules/@browserbasehq/stagehand/dist/assets/stagehand-extension.zip",
|
|
123
|
+
"Paste the uploaded extension ID into index.ts",
|
|
124
|
+
"browse functions dev index.ts",
|
|
125
|
+
"browse functions publish index.ts",
|
|
126
|
+
"Create a BROWSERBASE_API_KEY secret with browse cloud secrets create, then attach it with browse functions secrets attach",
|
|
93
127
|
],
|
|
94
128
|
}, null, 2));
|
|
95
129
|
}
|
|
@@ -99,6 +133,15 @@ function ensureCommand(command) {
|
|
|
99
133
|
fail(`${command} is required but was not found on PATH.`);
|
|
100
134
|
}
|
|
101
135
|
}
|
|
136
|
+
function readStagehandZodVersion(projectRoot) {
|
|
137
|
+
try {
|
|
138
|
+
const stagehandPackageJson = JSON.parse(readFileSync(join(projectRoot, "node_modules", "@browserbasehq", "stagehand", "package.json"), "utf8"));
|
|
139
|
+
return stagehandPackageJson.dependencies?.zod;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
102
145
|
function runPackageManager(packageManager, args, cwd) {
|
|
103
146
|
const result = spawnSync(packageManager, args, {
|
|
104
147
|
cwd,
|
|
@@ -122,14 +122,23 @@ function ensureArchiveLockfile(root, entries) {
|
|
|
122
122
|
}
|
|
123
123
|
const tempDir = join(tmpdir(), `bb-functions-lockgen-${randomUUID()}`);
|
|
124
124
|
mkdirSync(tempDir, { recursive: true });
|
|
125
|
-
|
|
126
|
-
const
|
|
125
|
+
// Copy the files that publish uploads, so npm resolves local dependencies the same way the build does.
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
const target = join(tempDir, entry);
|
|
128
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
129
|
+
copyFileSync(join(root, entry), target);
|
|
130
|
+
}
|
|
131
|
+
// Omit resolved URLs so the builder installs from its own registry rather than the one on your machine.
|
|
132
|
+
const result = spawnSync("npm", ["install", "--package-lock-only", "--omit-lockfile-registry-resolved"], {
|
|
127
133
|
cwd: tempDir,
|
|
128
134
|
stdio: "pipe",
|
|
129
135
|
});
|
|
130
136
|
if (result.status !== 0) {
|
|
131
137
|
rmSync(tempDir, { recursive: true, force: true });
|
|
132
|
-
|
|
138
|
+
const npmOutput = result.error
|
|
139
|
+
? result.error.message
|
|
140
|
+
: result.stderr.toString().trim();
|
|
141
|
+
fail(`Failed to generate package-lock.json for the Functions build archive.${npmOutput ? `\n${npmOutput}` : ""}`);
|
|
133
142
|
}
|
|
134
143
|
return {
|
|
135
144
|
entries: [...entries, "package-lock.json"].sort(),
|
package/oclif.manifest.json
CHANGED
|
@@ -5502,18 +5502,18 @@
|
|
|
5502
5502
|
"update.js"
|
|
5503
5503
|
]
|
|
5504
5504
|
},
|
|
5505
|
-
"cloud:
|
|
5505
|
+
"cloud:extensions:delete": {
|
|
5506
5506
|
"aliases": [],
|
|
5507
5507
|
"args": {
|
|
5508
5508
|
"id": {
|
|
5509
|
-
"description": "
|
|
5509
|
+
"description": "Extension ID.",
|
|
5510
5510
|
"name": "id",
|
|
5511
5511
|
"required": true
|
|
5512
5512
|
}
|
|
5513
5513
|
},
|
|
5514
|
-
"description": "
|
|
5514
|
+
"description": "Delete a Chrome extension.",
|
|
5515
5515
|
"examples": [
|
|
5516
|
-
"browse cloud
|
|
5516
|
+
"browse cloud extensions delete <extension-id>"
|
|
5517
5517
|
],
|
|
5518
5518
|
"flags": {
|
|
5519
5519
|
"api-key": {
|
|
@@ -5535,7 +5535,7 @@
|
|
|
5535
5535
|
},
|
|
5536
5536
|
"hasDynamicHelp": false,
|
|
5537
5537
|
"hiddenAliases": [],
|
|
5538
|
-
"id": "cloud:
|
|
5538
|
+
"id": "cloud:extensions:delete",
|
|
5539
5539
|
"pluginAlias": "browse",
|
|
5540
5540
|
"pluginName": "browse",
|
|
5541
5541
|
"pluginType": "core",
|
|
@@ -5545,17 +5545,22 @@
|
|
|
5545
5545
|
"dist",
|
|
5546
5546
|
"commands",
|
|
5547
5547
|
"cloud",
|
|
5548
|
-
"
|
|
5549
|
-
"
|
|
5548
|
+
"extensions",
|
|
5549
|
+
"delete.js"
|
|
5550
5550
|
]
|
|
5551
5551
|
},
|
|
5552
|
-
"cloud:
|
|
5552
|
+
"cloud:extensions:get": {
|
|
5553
5553
|
"aliases": [],
|
|
5554
|
-
"args": {
|
|
5555
|
-
|
|
5554
|
+
"args": {
|
|
5555
|
+
"id": {
|
|
5556
|
+
"description": "Extension ID.",
|
|
5557
|
+
"name": "id",
|
|
5558
|
+
"required": true
|
|
5559
|
+
}
|
|
5560
|
+
},
|
|
5561
|
+
"description": "Get a Chrome extension by ID.",
|
|
5556
5562
|
"examples": [
|
|
5557
|
-
"browse cloud
|
|
5558
|
-
"browse cloud projects list --json"
|
|
5563
|
+
"browse cloud extensions get <extension-id>"
|
|
5559
5564
|
],
|
|
5560
5565
|
"flags": {
|
|
5561
5566
|
"api-key": {
|
|
@@ -5573,35 +5578,11 @@
|
|
|
5573
5578
|
"helpValue": "<baseUrl>",
|
|
5574
5579
|
"multiple": false,
|
|
5575
5580
|
"type": "option"
|
|
5576
|
-
},
|
|
5577
|
-
"format": {
|
|
5578
|
-
"description": "Output format. Defaults to table in a terminal and JSON when piped.",
|
|
5579
|
-
"name": "format",
|
|
5580
|
-
"hasDynamicHelp": false,
|
|
5581
|
-
"helpValue": "<format>",
|
|
5582
|
-
"multiple": false,
|
|
5583
|
-
"options": [
|
|
5584
|
-
"table",
|
|
5585
|
-
"json"
|
|
5586
|
-
],
|
|
5587
|
-
"type": "option"
|
|
5588
|
-
},
|
|
5589
|
-
"json": {
|
|
5590
|
-
"description": "Print raw JSON output.",
|
|
5591
|
-
"name": "json",
|
|
5592
|
-
"allowNo": false,
|
|
5593
|
-
"type": "boolean"
|
|
5594
|
-
},
|
|
5595
|
-
"wide": {
|
|
5596
|
-
"description": "Show full table values without truncation.",
|
|
5597
|
-
"name": "wide",
|
|
5598
|
-
"allowNo": false,
|
|
5599
|
-
"type": "boolean"
|
|
5600
5581
|
}
|
|
5601
5582
|
},
|
|
5602
5583
|
"hasDynamicHelp": false,
|
|
5603
5584
|
"hiddenAliases": [],
|
|
5604
|
-
"id": "cloud:
|
|
5585
|
+
"id": "cloud:extensions:get",
|
|
5605
5586
|
"pluginAlias": "browse",
|
|
5606
5587
|
"pluginName": "browse",
|
|
5607
5588
|
"pluginType": "core",
|
|
@@ -5611,22 +5592,22 @@
|
|
|
5611
5592
|
"dist",
|
|
5612
5593
|
"commands",
|
|
5613
5594
|
"cloud",
|
|
5614
|
-
"
|
|
5615
|
-
"
|
|
5595
|
+
"extensions",
|
|
5596
|
+
"get.js"
|
|
5616
5597
|
]
|
|
5617
5598
|
},
|
|
5618
|
-
"cloud:
|
|
5599
|
+
"cloud:extensions:upload": {
|
|
5619
5600
|
"aliases": [],
|
|
5620
5601
|
"args": {
|
|
5621
|
-
"
|
|
5622
|
-
"description": "
|
|
5623
|
-
"name": "
|
|
5602
|
+
"file": {
|
|
5603
|
+
"description": "Path to extension ZIP file.",
|
|
5604
|
+
"name": "file",
|
|
5624
5605
|
"required": true
|
|
5625
5606
|
}
|
|
5626
5607
|
},
|
|
5627
|
-
"description": "
|
|
5608
|
+
"description": "Upload a Chrome extension ZIP file.",
|
|
5628
5609
|
"examples": [
|
|
5629
|
-
"browse cloud
|
|
5610
|
+
"browse cloud extensions upload ./extension.zip"
|
|
5630
5611
|
],
|
|
5631
5612
|
"flags": {
|
|
5632
5613
|
"api-key": {
|
|
@@ -5648,7 +5629,7 @@
|
|
|
5648
5629
|
},
|
|
5649
5630
|
"hasDynamicHelp": false,
|
|
5650
5631
|
"hiddenAliases": [],
|
|
5651
|
-
"id": "cloud:
|
|
5632
|
+
"id": "cloud:extensions:upload",
|
|
5652
5633
|
"pluginAlias": "browse",
|
|
5653
5634
|
"pluginName": "browse",
|
|
5654
5635
|
"pluginType": "core",
|
|
@@ -5658,22 +5639,22 @@
|
|
|
5658
5639
|
"dist",
|
|
5659
5640
|
"commands",
|
|
5660
5641
|
"cloud",
|
|
5661
|
-
"
|
|
5662
|
-
"
|
|
5642
|
+
"extensions",
|
|
5643
|
+
"upload.js"
|
|
5663
5644
|
]
|
|
5664
5645
|
},
|
|
5665
|
-
"cloud:
|
|
5646
|
+
"cloud:projects:get": {
|
|
5666
5647
|
"aliases": [],
|
|
5667
5648
|
"args": {
|
|
5668
5649
|
"id": {
|
|
5669
|
-
"description": "
|
|
5650
|
+
"description": "Project ID.",
|
|
5670
5651
|
"name": "id",
|
|
5671
5652
|
"required": true
|
|
5672
5653
|
}
|
|
5673
5654
|
},
|
|
5674
|
-
"description": "
|
|
5655
|
+
"description": "Get a project by ID.",
|
|
5675
5656
|
"examples": [
|
|
5676
|
-
"browse cloud
|
|
5657
|
+
"browse cloud projects get <project-id>"
|
|
5677
5658
|
],
|
|
5678
5659
|
"flags": {
|
|
5679
5660
|
"api-key": {
|
|
@@ -5695,7 +5676,7 @@
|
|
|
5695
5676
|
},
|
|
5696
5677
|
"hasDynamicHelp": false,
|
|
5697
5678
|
"hiddenAliases": [],
|
|
5698
|
-
"id": "cloud:
|
|
5679
|
+
"id": "cloud:projects:get",
|
|
5699
5680
|
"pluginAlias": "browse",
|
|
5700
5681
|
"pluginName": "browse",
|
|
5701
5682
|
"pluginType": "core",
|
|
@@ -5705,22 +5686,17 @@
|
|
|
5705
5686
|
"dist",
|
|
5706
5687
|
"commands",
|
|
5707
5688
|
"cloud",
|
|
5708
|
-
"
|
|
5709
|
-
"
|
|
5689
|
+
"projects",
|
|
5690
|
+
"get.js"
|
|
5710
5691
|
]
|
|
5711
5692
|
},
|
|
5712
|
-
"cloud:
|
|
5693
|
+
"cloud:projects:list": {
|
|
5713
5694
|
"aliases": [],
|
|
5714
|
-
"args": {
|
|
5715
|
-
|
|
5716
|
-
"description": "Extension ID.",
|
|
5717
|
-
"name": "id",
|
|
5718
|
-
"required": true
|
|
5719
|
-
}
|
|
5720
|
-
},
|
|
5721
|
-
"description": "Get a Chrome extension by ID.",
|
|
5695
|
+
"args": {},
|
|
5696
|
+
"description": "List projects visible to the current API key.",
|
|
5722
5697
|
"examples": [
|
|
5723
|
-
"browse cloud
|
|
5698
|
+
"browse cloud projects list",
|
|
5699
|
+
"browse cloud projects list --json"
|
|
5724
5700
|
],
|
|
5725
5701
|
"flags": {
|
|
5726
5702
|
"api-key": {
|
|
@@ -5738,11 +5714,35 @@
|
|
|
5738
5714
|
"helpValue": "<baseUrl>",
|
|
5739
5715
|
"multiple": false,
|
|
5740
5716
|
"type": "option"
|
|
5717
|
+
},
|
|
5718
|
+
"format": {
|
|
5719
|
+
"description": "Output format. Defaults to table in a terminal and JSON when piped.",
|
|
5720
|
+
"name": "format",
|
|
5721
|
+
"hasDynamicHelp": false,
|
|
5722
|
+
"helpValue": "<format>",
|
|
5723
|
+
"multiple": false,
|
|
5724
|
+
"options": [
|
|
5725
|
+
"table",
|
|
5726
|
+
"json"
|
|
5727
|
+
],
|
|
5728
|
+
"type": "option"
|
|
5729
|
+
},
|
|
5730
|
+
"json": {
|
|
5731
|
+
"description": "Print raw JSON output.",
|
|
5732
|
+
"name": "json",
|
|
5733
|
+
"allowNo": false,
|
|
5734
|
+
"type": "boolean"
|
|
5735
|
+
},
|
|
5736
|
+
"wide": {
|
|
5737
|
+
"description": "Show full table values without truncation.",
|
|
5738
|
+
"name": "wide",
|
|
5739
|
+
"allowNo": false,
|
|
5740
|
+
"type": "boolean"
|
|
5741
5741
|
}
|
|
5742
5742
|
},
|
|
5743
5743
|
"hasDynamicHelp": false,
|
|
5744
5744
|
"hiddenAliases": [],
|
|
5745
|
-
"id": "cloud:
|
|
5745
|
+
"id": "cloud:projects:list",
|
|
5746
5746
|
"pluginAlias": "browse",
|
|
5747
5747
|
"pluginName": "browse",
|
|
5748
5748
|
"pluginType": "core",
|
|
@@ -5752,22 +5752,22 @@
|
|
|
5752
5752
|
"dist",
|
|
5753
5753
|
"commands",
|
|
5754
5754
|
"cloud",
|
|
5755
|
-
"
|
|
5756
|
-
"
|
|
5755
|
+
"projects",
|
|
5756
|
+
"list.js"
|
|
5757
5757
|
]
|
|
5758
5758
|
},
|
|
5759
|
-
"cloud:
|
|
5759
|
+
"cloud:projects:usage": {
|
|
5760
5760
|
"aliases": [],
|
|
5761
5761
|
"args": {
|
|
5762
|
-
"
|
|
5763
|
-
"description": "
|
|
5764
|
-
"name": "
|
|
5762
|
+
"id": {
|
|
5763
|
+
"description": "Project ID.",
|
|
5764
|
+
"name": "id",
|
|
5765
5765
|
"required": true
|
|
5766
5766
|
}
|
|
5767
5767
|
},
|
|
5768
|
-
"description": "
|
|
5768
|
+
"description": "Get project usage.",
|
|
5769
5769
|
"examples": [
|
|
5770
|
-
"browse cloud
|
|
5770
|
+
"browse cloud projects usage <project-id>"
|
|
5771
5771
|
],
|
|
5772
5772
|
"flags": {
|
|
5773
5773
|
"api-key": {
|
|
@@ -5789,7 +5789,7 @@
|
|
|
5789
5789
|
},
|
|
5790
5790
|
"hasDynamicHelp": false,
|
|
5791
5791
|
"hiddenAliases": [],
|
|
5792
|
-
"id": "cloud:
|
|
5792
|
+
"id": "cloud:projects:usage",
|
|
5793
5793
|
"pluginAlias": "browse",
|
|
5794
5794
|
"pluginName": "browse",
|
|
5795
5795
|
"pluginType": "core",
|
|
@@ -5799,8 +5799,8 @@
|
|
|
5799
5799
|
"dist",
|
|
5800
5800
|
"commands",
|
|
5801
5801
|
"cloud",
|
|
5802
|
-
"
|
|
5803
|
-
"
|
|
5802
|
+
"projects",
|
|
5803
|
+
"usage.js"
|
|
5804
5804
|
]
|
|
5805
5805
|
},
|
|
5806
5806
|
"cloud:secrets:create": {
|
|
@@ -6903,5 +6903,5 @@
|
|
|
6903
6903
|
]
|
|
6904
6904
|
}
|
|
6905
6905
|
},
|
|
6906
|
-
"version": "0.11.
|
|
6906
|
+
"version": "0.11.1"
|
|
6907
6907
|
}
|