@canaryai/cli 0.2.9 → 0.2.12
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/dist/{chunk-C2PGZRYK.js → chunk-CEW4BDXD.js} +26 -7
- package/dist/chunk-CEW4BDXD.js.map +1 -0
- package/dist/chunk-ERSNYLMZ.js +229 -0
- package/dist/chunk-ERSNYLMZ.js.map +1 -0
- package/dist/{chunk-XGO62PO2.js → chunk-MSMC6UXW.js} +198 -11
- package/dist/{chunk-XGO62PO2.js.map → chunk-MSMC6UXW.js.map} +1 -1
- package/dist/{chunk-LC7ZVXPH.js → chunk-Q7WFBG5C.js} +2 -2
- package/dist/{debug-workflow-I3F36JBL.js → debug-workflow-53ULOFJC.js} +4 -4
- package/dist/{docs-REHST3YB.js → docs-BEE3LOCO.js} +2 -2
- package/dist/{feature-flag-3HB5NTMY.js → feature-flag-CYTDV4ZB.js} +2 -2
- package/dist/index.js +61 -139
- package/dist/index.js.map +1 -1
- package/dist/init-M6I3MG3D.js +146 -0
- package/dist/init-M6I3MG3D.js.map +1 -0
- package/dist/{issues-YU57CHXS.js → issues-NLM72HLU.js} +2 -2
- package/dist/{knobs-QJ4IBLCT.js → knobs-O35GAU5M.js} +2 -2
- package/dist/list-4K4EIGAT.js +57 -0
- package/dist/list-4K4EIGAT.js.map +1 -0
- package/dist/local-NHXXPHZ3.js +63 -0
- package/dist/local-NHXXPHZ3.js.map +1 -0
- package/dist/{local-browser-MKTJ36KY.js → local-browser-VAZORCO3.js} +3 -3
- package/dist/login-ZLP64YQP.js +130 -0
- package/dist/login-ZLP64YQP.js.map +1 -0
- package/dist/{mcp-ZOKM2AUE.js → mcp-ZF5G5DCB.js} +4 -126
- package/dist/mcp-ZF5G5DCB.js.map +1 -0
- package/dist/{record-TNDBT3NY.js → record-V6QKFFH3.js} +6 -47
- package/dist/record-V6QKFFH3.js.map +1 -0
- package/dist/{release-L4IXOHDF.js → release-7TI7EIGD.js} +8 -4
- package/dist/release-7TI7EIGD.js.map +1 -0
- package/dist/{session-RNLKFS2Z.js → session-UGNJXRUW.js} +138 -70
- package/dist/session-UGNJXRUW.js.map +1 -0
- package/dist/skill-ORWAPBDW.js +424 -0
- package/dist/skill-ORWAPBDW.js.map +1 -0
- package/dist/{src-2WSMYBMJ.js → src-4VIDSK4A.js} +2 -2
- package/dist/start-E532F3BU.js +112 -0
- package/dist/start-E532F3BU.js.map +1 -0
- package/dist/workflow-HXIUXRFI.js +613 -0
- package/dist/workflow-HXIUXRFI.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-C2PGZRYK.js.map +0 -1
- package/dist/chunk-DXIAHB72.js +0 -340
- package/dist/chunk-DXIAHB72.js.map +0 -1
- package/dist/chunk-QLFSJG5O.js +0 -93
- package/dist/chunk-QLFSJG5O.js.map +0 -1
- package/dist/mcp-ZOKM2AUE.js.map +0 -1
- package/dist/record-TNDBT3NY.js.map +0 -1
- package/dist/release-L4IXOHDF.js.map +0 -1
- package/dist/session-RNLKFS2Z.js.map +0 -1
- package/dist/skill-CZ7SHI3P.js +0 -156
- package/dist/skill-CZ7SHI3P.js.map +0 -1
- /package/dist/{chunk-LC7ZVXPH.js.map → chunk-Q7WFBG5C.js.map} +0 -0
- /package/dist/{debug-workflow-I3F36JBL.js.map → debug-workflow-53ULOFJC.js.map} +0 -0
- /package/dist/{docs-REHST3YB.js.map → docs-BEE3LOCO.js.map} +0 -0
- /package/dist/{feature-flag-3HB5NTMY.js.map → feature-flag-CYTDV4ZB.js.map} +0 -0
- /package/dist/{issues-YU57CHXS.js.map → issues-NLM72HLU.js.map} +0 -0
- /package/dist/{knobs-QJ4IBLCT.js.map → knobs-O35GAU5M.js.map} +0 -0
- /package/dist/{local-browser-MKTJ36KY.js.map → local-browser-VAZORCO3.js.map} +0 -0
- /package/dist/{src-2WSMYBMJ.js.map → src-4VIDSK4A.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local/init.ts"],"sourcesContent":["/**\n * `canary local init` — Interactive wizard for setting up local testing.\n *\n * Walks through: property selection, local URL, credential setup.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { resolveConfig } from '../auth.js';\nimport {\n selectProperty,\n promptInput,\n promptChoice,\n apiRequest,\n uploadStorageState,\n} from '../cli-helpers.js';\nimport {\n createSession,\n deleteSession,\n getSessionStorageState,\n} from '../session/daemon-client.js';\n\nexport async function runLocalInit(argv: string[]) {\n const config = await resolveConfig(argv);\n\n // 1. Select property\n console.log('\\n🔧 Local Testing Setup\\n');\n const property = await selectProperty(config.apiUrl, config.token);\n if (!property) {\n process.exitCode = 1;\n return;\n }\n\n // 2. Prompt for local URL\n const localUrl = await promptInput('What is the local testing URL?', 'http://localhost:3000');\n if (!localUrl) {\n console.error('URL is required.');\n process.exitCode = 1;\n return;\n }\n\n // 3. Create local environment\n const envName = `Local - ${localUrl}`;\n const envResult = await apiRequest<{\n ok: boolean;\n item?: { id: string; name: string };\n error?: string;\n }>(config.apiUrl, config.token, 'POST', `/org/properties/${property.id}/environments`, {\n name: envName,\n url: localUrl,\n type: 'local',\n });\n\n if (!envResult.ok || !envResult.item) {\n console.error(`Failed to create environment: ${envResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n console.log(`Created local environment: ${envResult.item.name}`);\n\n // 4. Credential setup\n const credentialChoice = await promptChoice('Does this app need credentials?', [\n { label: \"Yes, I'll enter username & password\", value: 'enter' },\n { label: \"No credentials, I'll log in myself\", value: 'manual' },\n { label: 'Skip — no login needed', value: 'skip' },\n ]);\n\n if (credentialChoice === 'enter') {\n await handleEnterCredentials(config, property.id, envResult.item.id, localUrl);\n } else if (credentialChoice === 'manual') {\n await handleManualLogin(config, property.id, envResult.item.id, localUrl);\n } else {\n console.log('\\nLocal environment ready. Run `canary local start` to begin.');\n }\n}\n\nasync function handleEnterCredentials(\n config: { apiUrl: string; token: string },\n propertyId: string,\n environmentId: string,\n localUrl: string\n) {\n const username = await promptInput('Username');\n const password = await promptInput('Password');\n\n if (!username || !password) {\n console.error('Username and password are required.');\n process.exitCode = 1;\n return;\n }\n\n const credResult = await apiRequest<{\n ok: boolean;\n item?: { id: string; name: string };\n error?: string;\n }>(config.apiUrl, config.token, 'POST', `/org/properties/${propertyId}/credentials`, {\n name: `Local - ${username}`,\n environmentId,\n authProvider: 'basic',\n data: { username, password },\n loginUrl: `${localUrl}/login`,\n });\n\n if (!credResult.ok) {\n console.error(`Failed to create credential: ${credResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n console.log(`\\nCreated credential: ${credResult.item?.name}`);\n console.log('Run `canary local start` to begin a session.');\n}\n\nasync function handleManualLogin(\n config: { apiUrl: string; token: string },\n propertyId: string,\n environmentId: string,\n localUrl: string\n) {\n // Create a minimal credential\n const credResult = await apiRequest<{\n ok: boolean;\n item?: { id: string; name: string };\n error?: string;\n }>(config.apiUrl, config.token, 'POST', `/org/properties/${propertyId}/credentials`, {\n name: 'Local - manual',\n environmentId,\n authProvider: 'custom',\n loginUrl: localUrl,\n });\n\n if (!credResult.ok || !credResult.item) {\n console.error(`Failed to create credential: ${credResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n const credentialId = credResult.item.id;\n\n // Start a headed session\n console.log('\\nOpening browser...');\n const sessionResult = await createSession({\n name: 'local-login',\n url: localUrl,\n });\n\n if (!sessionResult.ok || !sessionResult.data) {\n console.error(`Failed to start browser session: ${sessionResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n const sessionId = sessionResult.data.id;\n\n console.log(`Browser opened at ${localUrl}. Log in, then press Enter when done.`);\n\n // Wait for Enter keypress\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n await new Promise<void>((resolve) => {\n rl.question('', () => {\n rl.close();\n resolve();\n });\n });\n\n // Extract storage state\n console.log('Extracting login state...');\n const storageResult = await getSessionStorageState(sessionId);\n\n if (!storageResult.ok || !storageResult.data) {\n console.error(`Failed to extract storage state: ${storageResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n // Upload storage state\n console.log('Saving login state...');\n const uploadResult = await uploadStorageState({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId,\n credentialId,\n storageState: storageResult.data,\n });\n\n if (!uploadResult.ok) {\n console.error(`Failed to save login state: ${uploadResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n // Clean up login session\n await deleteSession(sessionId);\n\n console.log('\\nLogin state saved! Run `canary local start` to begin.');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
apiRequest
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ERSNYLMZ.js";
|
|
5
5
|
import {
|
|
6
6
|
getArgValue,
|
|
7
7
|
hasFlag,
|
|
@@ -361,4 +361,4 @@ async function runIssues(argv) {
|
|
|
361
361
|
export {
|
|
362
362
|
runIssues
|
|
363
363
|
};
|
|
364
|
-
//# sourceMappingURL=issues-
|
|
364
|
+
//# sourceMappingURL=issues-NLM72HLU.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
fetchList,
|
|
5
5
|
parseLifecycleStage,
|
|
6
6
|
toLifecycleLabel
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ERSNYLMZ.js";
|
|
8
8
|
import {
|
|
9
9
|
getArgValue,
|
|
10
10
|
hasFlag,
|
|
@@ -286,4 +286,4 @@ async function runKnobs(argv) {
|
|
|
286
286
|
export {
|
|
287
287
|
runKnobs
|
|
288
288
|
};
|
|
289
|
-
//# sourceMappingURL=knobs-
|
|
289
|
+
//# sourceMappingURL=knobs-O35GAU5M.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
fetchList,
|
|
4
|
+
fetchProperties
|
|
5
|
+
} from "./chunk-ERSNYLMZ.js";
|
|
6
|
+
import {
|
|
7
|
+
resolveConfig
|
|
8
|
+
} from "./chunk-PWWQGYFG.js";
|
|
9
|
+
import "./chunk-XAA5VQ5N.js";
|
|
10
|
+
import "./chunk-VKVL7WBN.js";
|
|
11
|
+
|
|
12
|
+
// src/local/list.ts
|
|
13
|
+
async function runLocalList(argv) {
|
|
14
|
+
const config = await resolveConfig(argv);
|
|
15
|
+
const properties = await fetchProperties(config.apiUrl, config.token);
|
|
16
|
+
if (properties.length === 0) {
|
|
17
|
+
console.log("No properties found.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const rows = [];
|
|
21
|
+
for (const property of properties) {
|
|
22
|
+
const envs = await fetchList(
|
|
23
|
+
config.apiUrl,
|
|
24
|
+
config.token,
|
|
25
|
+
`/org/properties/${property.id}/environments/local`,
|
|
26
|
+
"items"
|
|
27
|
+
);
|
|
28
|
+
for (const env of envs) {
|
|
29
|
+
rows.push({
|
|
30
|
+
envId: env.id,
|
|
31
|
+
property: property.name,
|
|
32
|
+
name: env.name,
|
|
33
|
+
url: env.url
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (rows.length === 0) {
|
|
38
|
+
console.log("No local environments found. Run `canary local init` to create one.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const headers = ["ENV ID", "PROPERTY", "NAME", "URL"];
|
|
42
|
+
const widths = headers.map((h, i) => {
|
|
43
|
+
const col = [h, ...rows.map((r) => Object.values(r)[i])];
|
|
44
|
+
return Math.max(...col.map((v) => v.length));
|
|
45
|
+
});
|
|
46
|
+
const sep = widths.map((w) => "-".repeat(w)).join(" ");
|
|
47
|
+
const formatRow = (vals) => vals.map((v, i) => v.padEnd(widths[i])).join(" ");
|
|
48
|
+
console.log(formatRow(headers));
|
|
49
|
+
console.log(sep);
|
|
50
|
+
for (const row of rows) {
|
|
51
|
+
console.log(formatRow([row.envId, row.property, row.name, row.url]));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
runLocalList
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=list-4K4EIGAT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local/list.ts"],"sourcesContent":["/**\n * `canary local list` — List all local environments for the current user.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { resolveConfig } from '../auth.js';\nimport { fetchProperties, fetchList } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalList(argv: string[]) {\n const config = await resolveConfig(argv);\n\n const properties = await fetchProperties(config.apiUrl, config.token);\n\n if (properties.length === 0) {\n console.log('No properties found.');\n return;\n }\n\n const rows: Array<{ envId: string; property: string; name: string; url: string }> = [];\n\n for (const property of properties) {\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n for (const env of envs) {\n rows.push({\n envId: env.id,\n property: property.name,\n name: env.name,\n url: env.url,\n });\n }\n }\n\n if (rows.length === 0) {\n console.log('No local environments found. Run `canary local init` to create one.');\n return;\n }\n\n // Print table\n const headers = ['ENV ID', 'PROPERTY', 'NAME', 'URL'];\n const widths = headers.map((h, i) => {\n const col = [h, ...rows.map((r) => Object.values(r)[i])];\n return Math.max(...col.map((v) => v.length));\n });\n\n const sep = widths.map((w) => '-'.repeat(w)).join(' ');\n const formatRow = (vals: string[]) =>\n vals.map((v, i) => v.padEnd(widths[i])).join(' ');\n\n console.log(formatRow(headers));\n console.log(sep);\n for (const row of rows) {\n console.log(formatRow([row.envId, row.property, row.name, row.url]));\n }\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,eAAsB,aAAa,MAAgB;AACjD,QAAM,SAAS,MAAM,cAAc,IAAI;AAEvC,QAAM,aAAa,MAAM,gBAAgB,OAAO,QAAQ,OAAO,KAAK;AAEpE,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAI,sBAAsB;AAClC;AAAA,EACF;AAEA,QAAM,OAA8E,CAAC;AAErF,aAAW,YAAY,YAAY;AACjC,UAAM,OAAO,MAAM;AAAA,MACjB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,mBAAmB,SAAS,EAAE;AAAA,MAC9B;AAAA,IACF;AAEA,eAAW,OAAO,MAAM;AACtB,WAAK,KAAK;AAAA,QACR,OAAO,IAAI;AAAA,QACX,UAAU,SAAS;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,IAAI,qEAAqE;AACjF;AAAA,EACF;AAGA,QAAM,UAAU,CAAC,UAAU,YAAY,QAAQ,KAAK;AACpD,QAAM,SAAS,QAAQ,IAAI,CAAC,GAAG,MAAM;AACnC,UAAM,MAAM,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACvD,WAAO,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,EAC7C,CAAC;AAED,QAAM,MAAM,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI;AACtD,QAAM,YAAY,CAAC,SACjB,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI;AAEnD,UAAQ,IAAI,UAAU,OAAO,CAAC;AAC9B,UAAQ,IAAI,GAAG;AACf,aAAW,OAAO,MAAM;AACtB,YAAQ,IAAI,UAAU,CAAC,IAAI,OAAO,IAAI,UAAU,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;AAAA,EACrE;AACF;","names":[]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
hasFlag
|
|
4
|
+
} from "./chunk-PWWQGYFG.js";
|
|
5
|
+
import "./chunk-VKVL7WBN.js";
|
|
6
|
+
|
|
7
|
+
// src/local/index.ts
|
|
8
|
+
import process from "process";
|
|
9
|
+
function printHelp() {
|
|
10
|
+
console.log(
|
|
11
|
+
[
|
|
12
|
+
"canary local \u2014 Manage local testing environments",
|
|
13
|
+
"",
|
|
14
|
+
"Sub-commands:",
|
|
15
|
+
" init Set up a new local testing environment",
|
|
16
|
+
" start Start a browser session for a local environment",
|
|
17
|
+
" list List local environments",
|
|
18
|
+
" login Re-login / refresh credentials",
|
|
19
|
+
"",
|
|
20
|
+
"Options:",
|
|
21
|
+
" --env <env> Environment (local, dev, prod)",
|
|
22
|
+
" --api-url <url> API URL override",
|
|
23
|
+
" -h, --help Show this help"
|
|
24
|
+
].join("\n")
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
async function runLocal(argv) {
|
|
28
|
+
const [subcommand, ...rest] = argv;
|
|
29
|
+
if (!subcommand || subcommand === "help" || hasFlag(argv, "--help", "-h")) {
|
|
30
|
+
printHelp();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
switch (subcommand) {
|
|
34
|
+
case "init": {
|
|
35
|
+
const { runLocalInit } = await import("./init-M6I3MG3D.js");
|
|
36
|
+
await runLocalInit(rest);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case "start": {
|
|
40
|
+
const { runLocalStart } = await import("./start-E532F3BU.js");
|
|
41
|
+
await runLocalStart(rest);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case "list": {
|
|
45
|
+
const { runLocalList } = await import("./list-4K4EIGAT.js");
|
|
46
|
+
await runLocalList(rest);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case "login": {
|
|
50
|
+
const { runLocalLogin } = await import("./login-ZLP64YQP.js");
|
|
51
|
+
await runLocalLogin(rest);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
default:
|
|
55
|
+
console.error(`Unknown sub-command: ${subcommand}`);
|
|
56
|
+
printHelp();
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
runLocal
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=local-NHXXPHZ3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local/index.ts"],"sourcesContent":["/**\n * CLI local command — `canary local <subcommand>`.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { hasFlag } from '../auth.js';\n\nfunction printHelp() {\n console.log(\n [\n 'canary local — Manage local testing environments',\n '',\n 'Sub-commands:',\n ' init Set up a new local testing environment',\n ' start Start a browser session for a local environment',\n ' list List local environments',\n ' login Re-login / refresh credentials',\n '',\n 'Options:',\n ' --env <env> Environment (local, dev, prod)',\n ' --api-url <url> API URL override',\n ' -h, --help Show this help',\n ].join('\\n')\n );\n}\n\nexport async function runLocal(argv: string[]) {\n const [subcommand, ...rest] = argv;\n\n if (!subcommand || subcommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n switch (subcommand) {\n case 'init': {\n const { runLocalInit } = await import('./init.js');\n await runLocalInit(rest);\n break;\n }\n case 'start': {\n const { runLocalStart } = await import('./start.js');\n await runLocalStart(rest);\n break;\n }\n case 'list': {\n const { runLocalList } = await import('./list.js');\n await runLocalList(rest);\n break;\n }\n case 'login': {\n const { runLocalLogin } = await import('./login.js');\n await runLocalLogin(rest);\n break;\n }\n default:\n console.error(`Unknown sub-command: ${subcommand}`);\n printHelp();\n process.exitCode = 1;\n }\n}\n"],"mappings":";;;;;;;AAMA,OAAO,aAAa;AAGpB,SAAS,YAAY;AACnB,UAAQ;AAAA,IACN;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAEA,eAAsB,SAAS,MAAgB;AAC7C,QAAM,CAAC,YAAY,GAAG,IAAI,IAAI;AAE9B,MAAI,CAAC,cAAc,eAAe,UAAU,QAAQ,MAAM,UAAU,IAAI,GAAG;AACzE,cAAU;AACV;AAAA,EACF;AAEA,UAAQ,YAAY;AAAA,IAClB,KAAK,QAAQ;AACX,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oBAAW;AACjD,YAAM,aAAa,IAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,YAAM,cAAc,IAAI;AACxB;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oBAAW;AACjD,YAAM,aAAa,IAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,YAAM,cAAc,IAAI;AACxB;AAAA,IACF;AAAA,IACA;AACE,cAAQ,MAAM,wBAAwB,UAAU,EAAE;AAClD,gBAAU;AACV,cAAQ,WAAW;AAAA,EACvB;AACF;","names":[]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
LocalBrowserHost
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Q7WFBG5C.js";
|
|
5
5
|
import {
|
|
6
6
|
readStoredToken
|
|
7
7
|
} from "./chunk-PWWQGYFG.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-MSMC6UXW.js";
|
|
9
9
|
import "./chunk-XAA5VQ5N.js";
|
|
10
10
|
import "./chunk-P5Z2Y5VV.js";
|
|
11
11
|
import "./chunk-VKVL7WBN.js";
|
|
@@ -141,4 +141,4 @@ async function runLocalBrowser(args) {
|
|
|
141
141
|
export {
|
|
142
142
|
runLocalBrowser
|
|
143
143
|
};
|
|
144
|
-
//# sourceMappingURL=local-browser-
|
|
144
|
+
//# sourceMappingURL=local-browser-VAZORCO3.js.map
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
fetchList,
|
|
4
|
+
promptChoice,
|
|
5
|
+
selectProperty,
|
|
6
|
+
uploadStorageState
|
|
7
|
+
} from "./chunk-ERSNYLMZ.js";
|
|
8
|
+
import {
|
|
9
|
+
createSession,
|
|
10
|
+
deleteSession,
|
|
11
|
+
getSessionStorageState
|
|
12
|
+
} from "./chunk-CEW4BDXD.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveConfig
|
|
15
|
+
} from "./chunk-PWWQGYFG.js";
|
|
16
|
+
import "./chunk-XAA5VQ5N.js";
|
|
17
|
+
import "./chunk-VKVL7WBN.js";
|
|
18
|
+
|
|
19
|
+
// src/local/login.ts
|
|
20
|
+
import process from "process";
|
|
21
|
+
async function runLocalLogin(argv) {
|
|
22
|
+
const config = await resolveConfig(argv);
|
|
23
|
+
const property = await selectProperty(config.apiUrl, config.token);
|
|
24
|
+
if (!property) {
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const envs = await fetchList(
|
|
29
|
+
config.apiUrl,
|
|
30
|
+
config.token,
|
|
31
|
+
`/org/properties/${property.id}/environments/local`,
|
|
32
|
+
"items"
|
|
33
|
+
);
|
|
34
|
+
if (envs.length === 0) {
|
|
35
|
+
console.error("No local environments found. Run `canary local init` first.");
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
let selectedEnv;
|
|
40
|
+
if (envs.length === 1) {
|
|
41
|
+
selectedEnv = envs[0];
|
|
42
|
+
} else {
|
|
43
|
+
const picked = await promptChoice(
|
|
44
|
+
"Select a local environment:",
|
|
45
|
+
envs.map((e) => ({ label: `${e.name} \u2014 ${e.url}`, value: e }))
|
|
46
|
+
);
|
|
47
|
+
if (!picked) {
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
selectedEnv = picked;
|
|
52
|
+
}
|
|
53
|
+
const allCredentials = await fetchList(
|
|
54
|
+
config.apiUrl,
|
|
55
|
+
config.token,
|
|
56
|
+
"/org/credentials",
|
|
57
|
+
"items"
|
|
58
|
+
);
|
|
59
|
+
const envCredentials = allCredentials.filter(
|
|
60
|
+
(c) => c.propertyId === property.id
|
|
61
|
+
);
|
|
62
|
+
if (envCredentials.length === 0) {
|
|
63
|
+
console.error("No credentials found for this property.");
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let credential;
|
|
68
|
+
if (envCredentials.length === 1) {
|
|
69
|
+
credential = envCredentials[0];
|
|
70
|
+
} else {
|
|
71
|
+
const picked = await promptChoice(
|
|
72
|
+
"Select a credential to refresh:",
|
|
73
|
+
envCredentials.map((c) => ({ label: c.name, value: c }))
|
|
74
|
+
);
|
|
75
|
+
if (!picked) {
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
credential = picked;
|
|
80
|
+
}
|
|
81
|
+
console.log(`
|
|
82
|
+
Opening browser at ${selectedEnv.url}...`);
|
|
83
|
+
const sessionResult = await createSession({
|
|
84
|
+
name: "local-login",
|
|
85
|
+
url: selectedEnv.url
|
|
86
|
+
});
|
|
87
|
+
if (!sessionResult.ok || !sessionResult.data) {
|
|
88
|
+
console.error(`Failed to start browser: ${sessionResult.error ?? "Unknown error"}`);
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const sessionId = sessionResult.data.id;
|
|
93
|
+
console.log("Log in, then press Enter when done.");
|
|
94
|
+
const readline = await import("readline");
|
|
95
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
96
|
+
await new Promise((resolve) => {
|
|
97
|
+
rl.question("", () => {
|
|
98
|
+
rl.close();
|
|
99
|
+
resolve();
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
console.log("Extracting login state...");
|
|
103
|
+
const storageResult = await getSessionStorageState(sessionId);
|
|
104
|
+
if (!storageResult.ok || !storageResult.data) {
|
|
105
|
+
console.error(`Failed to extract storage state: ${storageResult.error ?? "Unknown error"}`);
|
|
106
|
+
await deleteSession(sessionId);
|
|
107
|
+
process.exitCode = 1;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
console.log("Saving login state...");
|
|
111
|
+
const uploadResult = await uploadStorageState({
|
|
112
|
+
apiUrl: config.apiUrl,
|
|
113
|
+
token: config.token,
|
|
114
|
+
propertyId: property.id,
|
|
115
|
+
credentialId: credential.id,
|
|
116
|
+
storageState: storageResult.data
|
|
117
|
+
});
|
|
118
|
+
if (!uploadResult.ok) {
|
|
119
|
+
console.error(`Failed to save login state: ${uploadResult.error ?? "Unknown error"}`);
|
|
120
|
+
await deleteSession(sessionId);
|
|
121
|
+
process.exitCode = 1;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await deleteSession(sessionId);
|
|
125
|
+
console.log("\nLogin state refreshed! Run `canary local start` to begin.");
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
runLocalLogin
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=login-ZLP64YQP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local/login.ts"],"sourcesContent":["/**\n * `canary local login` — Re-login / refresh credentials for a local environment.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { resolveConfig } from '../auth.js';\nimport {\n selectProperty,\n promptChoice,\n fetchList,\n uploadStorageState,\n} from '../cli-helpers.js';\nimport {\n createSession,\n deleteSession,\n getSessionStorageState,\n} from '../session/daemon-client.js';\nimport type { CredentialListItem } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalLogin(argv: string[]) {\n const config = await resolveConfig(argv);\n\n // Select property\n const property = await selectProperty(config.apiUrl, config.token);\n if (!property) {\n process.exitCode = 1;\n return;\n }\n\n // Get local environments\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n if (envs.length === 0) {\n console.error('No local environments found. Run `canary local init` first.');\n process.exitCode = 1;\n return;\n }\n\n let selectedEnv: LocalEnvironment;\n if (envs.length === 1) {\n selectedEnv = envs[0];\n } else {\n const picked = await promptChoice(\n 'Select a local environment:',\n envs.map((e) => ({ label: `${e.name} — ${e.url}`, value: e }))\n );\n if (!picked) {\n process.exitCode = 1;\n return;\n }\n selectedEnv = picked;\n }\n\n // Find credentials for this property\n const allCredentials = await fetchList<CredentialListItem>(\n config.apiUrl,\n config.token,\n '/org/credentials',\n 'items'\n );\n\n const envCredentials = allCredentials.filter(\n (c) => c.propertyId === property.id\n );\n\n if (envCredentials.length === 0) {\n console.error('No credentials found for this property.');\n process.exitCode = 1;\n return;\n }\n\n let credential: CredentialListItem;\n if (envCredentials.length === 1) {\n credential = envCredentials[0];\n } else {\n const picked = await promptChoice(\n 'Select a credential to refresh:',\n envCredentials.map((c) => ({ label: c.name, value: c }))\n );\n if (!picked) {\n process.exitCode = 1;\n return;\n }\n credential = picked;\n }\n\n // Open headed session for login\n console.log(`\\nOpening browser at ${selectedEnv.url}...`);\n const sessionResult = await createSession({\n name: 'local-login',\n url: selectedEnv.url,\n });\n\n if (!sessionResult.ok || !sessionResult.data) {\n console.error(`Failed to start browser: ${sessionResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n const sessionId = sessionResult.data.id;\n\n console.log('Log in, then press Enter when done.');\n\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n await new Promise<void>((resolve) => {\n rl.question('', () => {\n rl.close();\n resolve();\n });\n });\n\n // Extract and upload storage state\n console.log('Extracting login state...');\n const storageResult = await getSessionStorageState(sessionId);\n\n if (!storageResult.ok || !storageResult.data) {\n console.error(`Failed to extract storage state: ${storageResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n console.log('Saving login state...');\n const uploadResult = await uploadStorageState({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n storageState: storageResult.data,\n });\n\n if (!uploadResult.ok) {\n console.error(`Failed to save login state: ${uploadResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n await deleteSession(sessionId);\n console.log('\\nLogin state refreshed! Run `canary local start` to begin.');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAMA,OAAO,aAAa;AAsBpB,eAAsB,cAAc,MAAgB;AAClD,QAAM,SAAS,MAAM,cAAc,IAAI;AAGvC,QAAM,WAAW,MAAM,eAAe,OAAO,QAAQ,OAAO,KAAK;AACjE,MAAI,CAAC,UAAU;AACb,YAAQ,WAAW;AACnB;AAAA,EACF;AAGA,QAAM,OAAO,MAAM;AAAA,IACjB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,mBAAmB,SAAS,EAAE;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,MAAM,6DAA6D;AAC3E,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,KAAK,WAAW,GAAG;AACrB,kBAAc,KAAK,CAAC;AAAA,EACtB,OAAO;AACL,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,KAAK,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,IAAI,WAAM,EAAE,GAAG,IAAI,OAAO,EAAE,EAAE;AAAA,IAC/D;AACA,QAAI,CAAC,QAAQ;AACX,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,kBAAc;AAAA,EAChB;AAGA,QAAM,iBAAiB,MAAM;AAAA,IAC3B,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF;AAEA,QAAM,iBAAiB,eAAe;AAAA,IACpC,CAAC,MAAM,EAAE,eAAe,SAAS;AAAA,EACnC;AAEA,MAAI,eAAe,WAAW,GAAG;AAC/B,YAAQ,MAAM,yCAAyC;AACvD,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,eAAe,WAAW,GAAG;AAC/B,iBAAa,eAAe,CAAC;AAAA,EAC/B,OAAO;AACL,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,eAAe,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,EAAE,EAAE;AAAA,IACzD;AACA,QAAI,CAAC,QAAQ;AACX,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,iBAAa;AAAA,EACf;AAGA,UAAQ,IAAI;AAAA,qBAAwB,YAAY,GAAG,KAAK;AACxD,QAAM,gBAAgB,MAAM,cAAc;AAAA,IACxC,MAAM;AAAA,IACN,KAAK,YAAY;AAAA,EACnB,CAAC;AAED,MAAI,CAAC,cAAc,MAAM,CAAC,cAAc,MAAM;AAC5C,YAAQ,MAAM,4BAA4B,cAAc,SAAS,eAAe,EAAE;AAClF,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,YAAY,cAAc,KAAK;AAErC,UAAQ,IAAI,qCAAqC;AAEjD,QAAM,WAAW,MAAM,OAAO,UAAe;AAC7C,QAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,OAAG,SAAS,IAAI,MAAM;AACpB,SAAG,MAAM;AACT,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAGD,UAAQ,IAAI,2BAA2B;AACvC,QAAM,gBAAgB,MAAM,uBAAuB,SAAS;AAE5D,MAAI,CAAC,cAAc,MAAM,CAAC,cAAc,MAAM;AAC5C,YAAQ,MAAM,oCAAoC,cAAc,SAAS,eAAe,EAAE;AAC1F,UAAM,cAAc,SAAS;AAC7B,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,UAAQ,IAAI,uBAAuB;AACnC,QAAM,eAAe,MAAM,mBAAmB;AAAA,IAC5C,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO;AAAA,IACd,YAAY,SAAS;AAAA,IACrB,cAAc,WAAW;AAAA,IACzB,cAAc,cAAc;AAAA,EAC9B,CAAC;AAED,MAAI,CAAC,aAAa,IAAI;AACpB,YAAQ,MAAM,+BAA+B,aAAa,SAAS,eAAe,EAAE;AACpF,UAAM,cAAc,SAAS;AAC7B,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,cAAc,SAAS;AAC7B,UAAQ,IAAI,6DAA6D;AAC3E;","names":[]}
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
LocalBrowserHost
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Q7WFBG5C.js";
|
|
5
5
|
import {
|
|
6
6
|
callTool,
|
|
7
7
|
createSession,
|
|
8
8
|
deleteAllSessions,
|
|
9
9
|
deleteSession,
|
|
10
10
|
resolveTargetSession
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import {
|
|
13
|
-
connectTunnel,
|
|
14
|
-
createLocalRun,
|
|
15
|
-
createTunnel
|
|
16
|
-
} from "./chunk-DXIAHB72.js";
|
|
11
|
+
} from "./chunk-CEW4BDXD.js";
|
|
17
12
|
import {
|
|
18
13
|
readStoredToken
|
|
19
14
|
} from "./chunk-PWWQGYFG.js";
|
|
20
15
|
import {
|
|
21
16
|
getBrowserToolDefinitionsWithLifecycle
|
|
22
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-MSMC6UXW.js";
|
|
23
18
|
import "./chunk-XAA5VQ5N.js";
|
|
24
19
|
import "./chunk-P5Z2Y5VV.js";
|
|
25
20
|
import "./chunk-VKVL7WBN.js";
|
|
@@ -51,7 +46,6 @@ function formatMCPContent(result) {
|
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
// src/mcp/session-tools.ts
|
|
54
|
-
import { createParser } from "eventsource-parser";
|
|
55
49
|
import process from "process";
|
|
56
50
|
var browserSessions = /* @__PURE__ */ new Map();
|
|
57
51
|
var DEFAULT_API_URL = "https://api.trycanary.ai";
|
|
@@ -67,30 +61,6 @@ async function resolveToken() {
|
|
|
67
61
|
}
|
|
68
62
|
function getSessionToolDefinitions() {
|
|
69
63
|
return [
|
|
70
|
-
{
|
|
71
|
-
name: "local_run_tests",
|
|
72
|
-
description: "Start an async local test run. A tunnel is opened automatically. Returns runId and watchUrl.",
|
|
73
|
-
inputSchema: {
|
|
74
|
-
type: "object",
|
|
75
|
-
properties: {
|
|
76
|
-
port: { type: "number" },
|
|
77
|
-
instructions: { type: "string" },
|
|
78
|
-
title: { type: "string" }
|
|
79
|
-
},
|
|
80
|
-
required: ["port", "instructions"]
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: "local_wait_for_results",
|
|
85
|
-
description: "Wait for a local test run to complete. Streams until completion and returns a compact report.",
|
|
86
|
-
inputSchema: {
|
|
87
|
-
type: "object",
|
|
88
|
-
properties: {
|
|
89
|
-
runId: { type: "string" }
|
|
90
|
-
},
|
|
91
|
-
required: ["runId"]
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
64
|
{
|
|
95
65
|
name: "local_browser_start",
|
|
96
66
|
description: "Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.",
|
|
@@ -177,38 +147,6 @@ function getSessionToolDefinitions() {
|
|
|
177
147
|
}
|
|
178
148
|
async function handleSessionTool(tool, args) {
|
|
179
149
|
const token = await resolveToken();
|
|
180
|
-
if (tool === "local_run_tests") {
|
|
181
|
-
const input = args;
|
|
182
|
-
const apiUrl = resolveApiUrl();
|
|
183
|
-
const tunnel = await createTunnel({ apiUrl, token, port: input.port });
|
|
184
|
-
connectTunnel({
|
|
185
|
-
apiUrl,
|
|
186
|
-
tunnelId: tunnel.tunnelId,
|
|
187
|
-
token: tunnel.token,
|
|
188
|
-
port: input.port
|
|
189
|
-
});
|
|
190
|
-
const tunnelUrl = tunnel.publicUrl;
|
|
191
|
-
const run = await createLocalRun({
|
|
192
|
-
apiUrl,
|
|
193
|
-
token,
|
|
194
|
-
title: input.title ?? "Local MCP run",
|
|
195
|
-
featureSpec: input.instructions,
|
|
196
|
-
startUrl: void 0,
|
|
197
|
-
tunnelUrl
|
|
198
|
-
});
|
|
199
|
-
return toolJson({
|
|
200
|
-
runId: run.runId,
|
|
201
|
-
watchUrl: run.watchUrl,
|
|
202
|
-
tunnelUrl,
|
|
203
|
-
note: "Testing is asynchronous. Use local_wait_for_results with the runId to wait for completion."
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
if (tool === "local_wait_for_results") {
|
|
207
|
-
const input = args;
|
|
208
|
-
const apiUrl = resolveApiUrl();
|
|
209
|
-
const report = await waitForResult({ apiUrl, token, runId: input.runId });
|
|
210
|
-
return toolJson(report);
|
|
211
|
-
}
|
|
212
150
|
if (tool === "local_browser_start") {
|
|
213
151
|
const input = args;
|
|
214
152
|
const apiUrl = resolveApiUrl();
|
|
@@ -338,66 +276,6 @@ async function handleSessionTool(tool, args) {
|
|
|
338
276
|
}
|
|
339
277
|
return null;
|
|
340
278
|
}
|
|
341
|
-
async function waitForResult(input) {
|
|
342
|
-
await streamUntilComplete(input);
|
|
343
|
-
const response = await fetch(`${input.apiUrl}/local-tests/runs/${input.runId}`, {
|
|
344
|
-
credentials: "include",
|
|
345
|
-
headers: { authorization: `Bearer ${input.token}` }
|
|
346
|
-
});
|
|
347
|
-
const data = await response.json();
|
|
348
|
-
const run = data?.data?.run ?? data?.run ?? data?.data;
|
|
349
|
-
const summary = run?.summaryJson;
|
|
350
|
-
return formatReport({ run, summary });
|
|
351
|
-
}
|
|
352
|
-
async function streamUntilComplete(input) {
|
|
353
|
-
const response = await fetch(`${input.apiUrl}/local-tests/runs/${input.runId}/stream`, {
|
|
354
|
-
headers: { authorization: `Bearer ${input.token}` }
|
|
355
|
-
});
|
|
356
|
-
if (!response.body) return;
|
|
357
|
-
const reader = response.body.getReader();
|
|
358
|
-
const decoder = new TextDecoder();
|
|
359
|
-
const parser = createParser({
|
|
360
|
-
onEvent: (event) => {
|
|
361
|
-
if (event.event === "status") {
|
|
362
|
-
try {
|
|
363
|
-
const payload = JSON.parse(event.data);
|
|
364
|
-
if (payload?.status === "completed" || payload?.status === "failed") {
|
|
365
|
-
reader.cancel().catch(() => void 0);
|
|
366
|
-
}
|
|
367
|
-
} catch {
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
if (event.event === "complete" || event.event === "error") {
|
|
371
|
-
reader.cancel().catch(() => void 0);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
while (true) {
|
|
376
|
-
const { done, value } = await reader.read();
|
|
377
|
-
if (done) break;
|
|
378
|
-
parser.feed(decoder.decode(value, { stream: true }));
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
function formatReport(input) {
|
|
382
|
-
if (!input.summary) {
|
|
383
|
-
return {
|
|
384
|
-
runId: input.run?.id,
|
|
385
|
-
status: input.run?.status ?? "unknown",
|
|
386
|
-
summary: "No final report available."
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
const tested = Array.isArray(input.summary.testedItems) ? input.summary.testedItems : [];
|
|
390
|
-
const status = input.summary.status ?? input.run?.status ?? "unknown";
|
|
391
|
-
const issues = status === "issues_found" ? input.summary.notes ? [input.summary.notes] : ["Issues reported."] : [];
|
|
392
|
-
return {
|
|
393
|
-
runId: input.run?.id,
|
|
394
|
-
status,
|
|
395
|
-
summary: input.summary.summary ?? "Run completed.",
|
|
396
|
-
testedItems: tested,
|
|
397
|
-
issues,
|
|
398
|
-
notes: input.summary.notes ?? null
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
279
|
|
|
402
280
|
// src/mcp/browser-tools.ts
|
|
403
281
|
var activeSessionId = null;
|
|
@@ -496,4 +374,4 @@ async function runMcp(argv) {
|
|
|
496
374
|
export {
|
|
497
375
|
runMcp
|
|
498
376
|
};
|
|
499
|
-
//# sourceMappingURL=mcp-
|
|
377
|
+
//# sourceMappingURL=mcp-ZF5G5DCB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/index.ts","../src/mcp/tool-helpers.ts","../src/mcp/session-tools.ts","../src/mcp/browser-tools.ts"],"sourcesContent":["/**\n * MCP Server for Canary CLI.\n *\n * Combines cloud-relay session tools and direct browser tools\n * into a single MCP server.\n *\n * @module\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { toolText } from './tool-helpers';\nimport { getSessionToolDefinitions, handleSessionTool } from './session-tools';\nimport { getBrowserMCPToolDefinitions, handleBrowserTool } from './browser-tools';\n\nexport async function runMcp(argv: string[]) {\n const server = new Server(\n { name: 'canary-cli', version: '0.1.0' },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...getSessionToolDefinitions(),\n ...getBrowserMCPToolDefinitions(),\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = req.params.name;\n const args = (req.params.arguments ?? {}) as Record<string, unknown>;\n\n // Try browser tools first (browser_* prefix)\n const browserResult = await handleBrowserTool(tool, args);\n if (browserResult) return browserResult;\n\n // Try session tools (local_* prefix)\n const sessionResult = await handleSessionTool(tool, args);\n if (sessionResult) return sessionResult;\n\n return toolText(`Unknown tool: ${tool}`);\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n return new Promise<void>(() => undefined);\n}\n","/**\n * MCP tool response helpers.\n *\n * @module\n */\n\nimport type { ToolResult } from '@chatsdet/browser-core';\n\nexport function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\n/**\n * Convert a BrowserToolExecutor result to MCP SDK content blocks.\n */\nexport function formatMCPContent(result: ToolResult) {\n if (typeof result === 'string') {\n return { content: [{ type: 'text' as const, text: result }] };\n }\n\n // MCPContentResult with text and optional images\n const content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }> = [];\n\n if (result.text) {\n content.push({ type: 'text', text: result.text });\n }\n\n for (const img of result.images ?? []) {\n content.push({ type: 'image', data: img.data, mimeType: img.mimeType });\n }\n\n return { content };\n}\n","/**\n * Cloud-relay session tools for the MCP server.\n *\n * These tools proxy browser control through the cloud API via WebSocket.\n *\n * @module\n */\n\nimport { readStoredToken } from '../auth';\nimport { LocalBrowserHost } from '../local-browser/host';\nimport type { LocalBrowserMode } from '../local-browser/protocol';\nimport { toolText, toolJson } from './tool-helpers';\n\nimport process from 'node:process';\n\ntype LocalBrowserStartInput = {\n mode?: LocalBrowserMode;\n cdpUrl?: string;\n headless?: boolean;\n storageStatePath?: string;\n instructions?: string;\n};\n\ntype LocalBrowserStopInput = {\n sessionId: string;\n};\n\ntype LocalBrowserStatusInput = {\n sessionId: string;\n};\n\ninterface BrowserSession {\n sessionId: string;\n host: LocalBrowserHost;\n startedAt: number;\n mode: LocalBrowserMode;\n}\n\n// Global browser sessions managed by MCP\nconst browserSessions = new Map<string, BrowserSession>();\n\nconst DEFAULT_API_URL = 'https://api.trycanary.ai';\n\nfunction resolveApiUrl(input?: string): string {\n return input ?? process.env.CANARY_API_URL ?? DEFAULT_API_URL;\n}\n\nasync function resolveToken(): Promise<string> {\n const token = process.env.CANARY_API_TOKEN ?? (await readStoredToken());\n if (!token) {\n throw new Error('Missing token. Run `canary login` first or set CANARY_API_TOKEN.');\n }\n return token;\n}\n\nexport function getSessionToolDefinitions() {\n return [\n {\n name: 'local_browser_start',\n description:\n 'Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.',\n inputSchema: {\n type: 'object',\n properties: {\n mode: {\n type: 'string',\n enum: ['playwright', 'cdp'],\n description: \"Browser mode: 'playwright' for fresh browser, 'cdp' to connect to existing Chrome\",\n },\n cdpUrl: {\n type: 'string',\n description: 'CDP endpoint URL when mode is \\'cdp\\' (e.g. http://localhost:9222)',\n },\n headless: {\n type: 'boolean',\n description: 'Run browser headless (default: true for playwright mode)',\n },\n storageStatePath: {\n type: 'string',\n description: 'Path to Playwright storage state JSON for pre-authenticated sessions',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n },\n },\n },\n {\n name: 'local_browser_status',\n description: 'Check the status of a local browser session.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_stop',\n description: 'Stop a local browser session and close the browser.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_list',\n description: 'List all active local browser sessions.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'local_browser_run',\n description:\n 'Start a test run on an active local browser session. The cloud agent will control the local browser according to the instructions.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID from local_browser_start',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n startUrl: {\n type: 'string',\n description: 'Optional URL to navigate to before starting',\n },\n },\n required: ['sessionId', 'instructions'],\n },\n },\n ];\n}\n\nexport async function handleSessionTool(tool: string, args: Record<string, unknown>) {\n const token = await resolveToken();\n\n if (tool === 'local_browser_start') {\n const input = args as unknown as LocalBrowserStartInput;\n const apiUrl = resolveApiUrl();\n const mode = input.mode ?? 'playwright';\n\n const sessionResponse = await fetch(`${apiUrl}/local-browser/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n browserMode: mode,\n instructions: input.instructions ?? null,\n }),\n });\n\n if (!sessionResponse.ok) {\n const text = await sessionResponse.text();\n return toolJson({ ok: false, error: `Failed to create session: ${text}` });\n }\n\n const session = (await sessionResponse.json()) as {\n ok: boolean;\n sessionId: string;\n wsToken: string;\n expiresAt: string;\n };\n\n const host = new LocalBrowserHost({\n apiUrl,\n wsToken: session.wsToken,\n sessionId: session.sessionId,\n browserMode: mode,\n cdpUrl: input.cdpUrl,\n headless: input.headless ?? true,\n storageStatePath: input.storageStatePath,\n onLog: (level, message) => {\n if (level === 'error') {\n console.error(`[LocalBrowser] ${message}`);\n }\n },\n });\n\n host.start().catch((err) => {\n console.error('Failed to start local browser:', err);\n browserSessions.delete(session.sessionId);\n });\n\n browserSessions.set(session.sessionId, {\n sessionId: session.sessionId,\n host,\n startedAt: Date.now(),\n mode,\n });\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode,\n expiresAt: session.expiresAt,\n note: 'Browser session started. The cloud agent can now control this browser. Use local_browser_stop to end the session.',\n });\n }\n\n if (tool === 'local_browser_status') {\n const input = args as unknown as LocalBrowserStatusInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode: session.mode,\n startedAt: new Date(session.startedAt).toISOString(),\n uptimeMs: Date.now() - session.startedAt,\n });\n }\n\n if (tool === 'local_browser_stop') {\n const input = args as unknown as LocalBrowserStopInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n await session.host.stop();\n browserSessions.delete(input.sessionId);\n\n return toolJson({\n ok: true,\n sessionId: input.sessionId,\n note: 'Browser session stopped and browser closed.',\n });\n }\n\n if (tool === 'local_browser_list') {\n const sessions = Array.from(browserSessions.values()).map((s) => ({\n sessionId: s.sessionId,\n mode: s.mode,\n startedAt: new Date(s.startedAt).toISOString(),\n uptimeMs: Date.now() - s.startedAt,\n }));\n\n return toolJson({\n ok: true,\n count: sessions.length,\n sessions,\n });\n }\n\n if (tool === 'local_browser_run') {\n const input = args as unknown as {\n sessionId: string;\n instructions: string;\n startUrl?: string;\n };\n const apiUrl = resolveApiUrl();\n\n const session = browserSessions.get(input.sessionId);\n if (!session) {\n return toolJson({\n ok: false,\n error: 'Session not found locally. Make sure you started it with local_browser_start.',\n sessionId: input.sessionId,\n });\n }\n\n const response = await fetch(`${apiUrl}/local-browser/sessions/${input.sessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n instructions: input.instructions,\n startUrl: input.startUrl ?? null,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n return toolJson({ ok: false, error: `Failed to start run: ${text}` });\n }\n\n const result = (await response.json()) as { ok: boolean; jobId: string; sessionId: string };\n\n return toolJson({\n ok: true,\n jobId: result.jobId,\n sessionId: result.sessionId,\n note: 'Test run started. The cloud agent is now controlling your local browser. You can watch the browser to see the test in action.',\n });\n }\n\n return null; // Not handled\n}\n","/**\n * Browser MCP tool registration — daemon adapter.\n *\n * Thin layer that maps MCP tool calls to the session daemon,\n * ensuring the CLI gets the SAME semantic diff, snapshot formatting,\n * click validation, auto-snapshot, and recovery notices as the cloud agent.\n *\n * The daemon owns all browser sessions. MCP is just a protocol adapter.\n *\n * @module\n */\n\nimport { getBrowserToolDefinitionsWithLifecycle } from '@chatsdet/browser-core';\nimport {\n createSession,\n deleteSession,\n deleteAllSessions,\n callTool,\n resolveTargetSession,\n listSessions,\n} from '../session/daemon-client.js';\nimport { formatMCPContent, toolJson } from './tool-helpers';\nimport type { ToolResult } from '@chatsdet/browser-core';\n\n/** Track the active session ID within this MCP server instance */\nlet activeSessionId: string | null = null;\n\n/**\n * Get tool definitions for browser MCP tools (including lifecycle).\n */\nexport function getBrowserMCPToolDefinitions() {\n return getBrowserToolDefinitionsWithLifecycle();\n}\n\n/**\n * Handle a browser tool call.\n * Returns null if the tool name is not a browser tool.\n */\nexport async function handleBrowserTool(name: string, args: Record<string, unknown>) {\n // Lifecycle tools\n if (name === 'browser_start') {\n try {\n const result = await createSession({\n headless: (args.headless as boolean) ?? false,\n storageStatePath: args.storageStatePath as string | undefined,\n });\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error });\n }\n\n activeSessionId = result.data!.id;\n return toolJson({\n ok: true,\n sessionId: activeSessionId,\n note: 'Browser started. You can now use browser_navigate, browser_click, and other browser tools.',\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (name === 'browser_stop') {\n try {\n if (activeSessionId) {\n await deleteSession(activeSessionId);\n activeSessionId = null;\n } else {\n // Stop all sessions if no specific one tracked\n await deleteAllSessions();\n }\n return toolJson({ ok: true, note: 'Browser stopped and cleaned up.' });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n // All other browser_* tools require an active session\n if (!name.startsWith('browser_')) return null;\n\n try {\n // Resolve target session: prefer tracked MCP session, then auto-resolve\n let sessionId = activeSessionId;\n if (!sessionId) {\n try {\n const target = await resolveTargetSession();\n sessionId = target.id;\n activeSessionId = sessionId;\n } catch {\n return toolJson({\n ok: false,\n error: 'No active browser session. Start one with browser_start first.',\n });\n }\n }\n\n // Strip 'browser_' prefix for the daemon tool name\n const toolName = name.replace(/^browser_/, '');\n const result = await callTool(sessionId, toolName, args);\n\n if (!result.ok) {\n // If session not found, clear tracking and report error\n if (result.error?.includes('not found')) {\n activeSessionId = null;\n }\n return toolJson({ ok: false, error: result.error, tool: name });\n }\n\n // Convert daemon response back to ToolResult format for MCP formatting\n const toolResult: ToolResult = result.images?.length\n ? { text: result.text ?? '', images: result.images }\n : result.text ?? '';\n\n return formatMCPContent(toolResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return toolJson({ ok: false, error: message, tool: name });\n }\n}\n"],"mappings":"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","names":[]}
|