@magic-markdown/cli 0.3.5 → 0.3.6
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/index.js +73 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10990,7 +10990,7 @@ var RemoteDocumentIO = class {
|
|
|
10990
10990
|
};
|
|
10991
10991
|
|
|
10992
10992
|
// src/agent.ts
|
|
10993
|
-
var CLI_VERSION = "0.3.
|
|
10993
|
+
var CLI_VERSION = "0.3.6";
|
|
10994
10994
|
var CLI_PACKAGE_NAME = "@magic-markdown/cli";
|
|
10995
10995
|
var AGENT_COMMANDS = [
|
|
10996
10996
|
{
|
|
@@ -11252,11 +11252,15 @@ var AGENT_COMMANDS = [
|
|
|
11252
11252
|
{
|
|
11253
11253
|
name: "bridge",
|
|
11254
11254
|
summary: "Sync a local Markdown root with a Magic workspace over WebSocket (long-running).",
|
|
11255
|
-
usage: "mdocs bridge --workspace <id> --root <path> --url <base-url>",
|
|
11255
|
+
usage: "mdocs bridge --workspace <id> --root <path> --url <base-url> --request-token",
|
|
11256
11256
|
output: "long-running",
|
|
11257
11257
|
mutates: true,
|
|
11258
|
-
examples: ["mdocs bridge --workspace workspace_abc --root . --root-id root_abc --url https://magic.example.com"],
|
|
11259
|
-
notes: [
|
|
11258
|
+
examples: ["mdocs bridge --workspace workspace_abc --root . --root-id root_abc --url https://magic.example.com --request-token"],
|
|
11259
|
+
notes: [
|
|
11260
|
+
"--request-token opens a human approval URL and avoids pasting bridge secrets into an agent session.",
|
|
11261
|
+
"--token (or MDOCS_BRIDGE_TOKEN) still works when a scoped bridge token is already available.",
|
|
11262
|
+
"--url (or MDOCS_BASE_URL) is required; the bridge never assumes a localhost server."
|
|
11263
|
+
]
|
|
11260
11264
|
},
|
|
11261
11265
|
{
|
|
11262
11266
|
name: "serve-mcp",
|
|
@@ -13367,6 +13371,7 @@ async function runBridge(options) {
|
|
|
13367
13371
|
const root = resolve4(options.root);
|
|
13368
13372
|
const localManifestSource = await readLocalSource(root);
|
|
13369
13373
|
const rootId = options.rootId ?? options.sourceId ?? localManifestSource?.sourceId ?? rootIdForPath(root);
|
|
13374
|
+
const token = options.token ?? (options.requestToken ? await requestBridgeToken(options, rootId) : void 0);
|
|
13370
13375
|
const replicaId = `replica_${createHash2("sha256").update(`${root}:${options.actorId}`).digest("hex").slice(0, 12)}`;
|
|
13371
13376
|
const replicaKind = actorKindForBridge(options.actorId) === "agent" ? "agent_runtime" : "local";
|
|
13372
13377
|
const mapping = createSourceMapping({
|
|
@@ -13389,7 +13394,7 @@ async function runBridge(options) {
|
|
|
13389
13394
|
const claimMode = Boolean(options.claimToken || localManifestSource?.canonicalHead);
|
|
13390
13395
|
let lastAppliedHead = localManifestSource?.canonicalHead;
|
|
13391
13396
|
let socket;
|
|
13392
|
-
const registeredRoot =
|
|
13397
|
+
const registeredRoot = token ? await fetchScopedRoot({ ...options, token }, rootId) : await registerRoot(options, root, rootId, mapping);
|
|
13393
13398
|
lastAppliedHead = lastAppliedHead ?? registeredRoot?.canonical.head;
|
|
13394
13399
|
await writeSourceState(lastAppliedHead);
|
|
13395
13400
|
connect();
|
|
@@ -13412,7 +13417,7 @@ async function runBridge(options) {
|
|
|
13412
13417
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
13413
13418
|
url.searchParams.set("actorId", options.actorId);
|
|
13414
13419
|
url.searchParams.set("sourceId", sourceId);
|
|
13415
|
-
if (
|
|
13420
|
+
if (token) url.searchParams.set("token", token);
|
|
13416
13421
|
socket = new WebSocket(url);
|
|
13417
13422
|
socket.addEventListener("open", () => {
|
|
13418
13423
|
process.stdout.write(`mdocs bridge connected ${root} -> ${options.workspaceId}/${rootId}
|
|
@@ -13574,7 +13579,7 @@ async function runBridge(options) {
|
|
|
13574
13579
|
`/api/workspaces/${encodeURIComponent(options.workspaceId)}/roots/${encodeURIComponent(rootId)}/documents/${encodeURIComponent(docId)}`,
|
|
13575
13580
|
options.baseUrl
|
|
13576
13581
|
),
|
|
13577
|
-
{ headers: authHeaders(
|
|
13582
|
+
{ headers: authHeaders(token) }
|
|
13578
13583
|
);
|
|
13579
13584
|
if (!response.ok) return void 0;
|
|
13580
13585
|
const document = await response.json();
|
|
@@ -13633,6 +13638,60 @@ async function runBridge(options) {
|
|
|
13633
13638
|
});
|
|
13634
13639
|
}
|
|
13635
13640
|
}
|
|
13641
|
+
async function requestBridgeToken(options, rootId) {
|
|
13642
|
+
const response = await fetch(new URL("/api/bridge-requests", options.baseUrl), {
|
|
13643
|
+
method: "POST",
|
|
13644
|
+
headers: { "Content-Type": "application/json" },
|
|
13645
|
+
body: JSON.stringify({
|
|
13646
|
+
workspaceId: options.workspaceId,
|
|
13647
|
+
rootId,
|
|
13648
|
+
actorId: options.actorId,
|
|
13649
|
+
actorName: options.actorName,
|
|
13650
|
+
sourceName: options.sourceName,
|
|
13651
|
+
role: "edit"
|
|
13652
|
+
})
|
|
13653
|
+
}).catch((error) => {
|
|
13654
|
+
throw new Error(`Failed to create bridge approval request: ${error instanceof Error ? error.message : String(error)}`);
|
|
13655
|
+
});
|
|
13656
|
+
if (!response.ok) {
|
|
13657
|
+
throw new Error(`Failed to create bridge approval request: ${response.status} ${await response.text()}`);
|
|
13658
|
+
}
|
|
13659
|
+
const created = await response.json();
|
|
13660
|
+
if (!created.requestId || !created.pollToken || !created.approveUrl) {
|
|
13661
|
+
throw new Error("Bridge approval request response was missing requestId, pollToken, or approveUrl.");
|
|
13662
|
+
}
|
|
13663
|
+
process.stdout.write(`mdocs bridge approval needed: ${created.approveUrl}
|
|
13664
|
+
`);
|
|
13665
|
+
if (created.expiresAt) process.stdout.write(`Waiting for approval until ${created.expiresAt}.
|
|
13666
|
+
`);
|
|
13667
|
+
const deadline = Date.now() + (options.pairingTimeoutMs ?? 1e3 * 60 * 15);
|
|
13668
|
+
while (Date.now() < deadline) {
|
|
13669
|
+
await delay(2e3);
|
|
13670
|
+
const pollResponse = await fetch(new URL(`/api/bridge-requests/${encodeURIComponent(created.requestId)}/token`, options.baseUrl), {
|
|
13671
|
+
headers: { Authorization: `Bearer ${created.pollToken}` }
|
|
13672
|
+
}).catch((error) => {
|
|
13673
|
+
throw new Error(`Bridge approval polling failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
13674
|
+
});
|
|
13675
|
+
const payload = await pollResponse.json().catch(() => ({}));
|
|
13676
|
+
if (pollResponse.status === 202) continue;
|
|
13677
|
+
if (pollResponse.ok && payload.token) {
|
|
13678
|
+
process.stdout.write(`mdocs bridge approved${payload.expiresAt ? `; token expires ${payload.expiresAt}` : ""}.
|
|
13679
|
+
`);
|
|
13680
|
+
return payload.token;
|
|
13681
|
+
}
|
|
13682
|
+
if (pollResponse.status === 409 && payload.status === "rejected") {
|
|
13683
|
+
throw new Error("Bridge approval request was rejected.");
|
|
13684
|
+
}
|
|
13685
|
+
if (pollResponse.status === 410 || payload.status === "expired") {
|
|
13686
|
+
throw new Error("Bridge approval request expired before it was approved.");
|
|
13687
|
+
}
|
|
13688
|
+
throw new Error(`Bridge approval polling failed with status ${pollResponse.status}.`);
|
|
13689
|
+
}
|
|
13690
|
+
throw new Error("Bridge approval timed out before a token was issued.");
|
|
13691
|
+
}
|
|
13692
|
+
function delay(ms) {
|
|
13693
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
13694
|
+
}
|
|
13636
13695
|
function authHeaders(token) {
|
|
13637
13696
|
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
13638
13697
|
}
|
|
@@ -13929,7 +13988,9 @@ async function main() {
|
|
|
13929
13988
|
actorName: typeof parsed.flags["actor-name"] === "string" ? parsed.flags["actor-name"] : void 0,
|
|
13930
13989
|
baseUrl: bridgeBaseUrl(parsed.flags),
|
|
13931
13990
|
intervalMs: Number(parsed.flags.interval ?? 1e3),
|
|
13932
|
-
token: typeof parsed.flags.token === "string" ? parsed.flags.token : process.env.MDOCS_BRIDGE_TOKEN || void 0
|
|
13991
|
+
token: typeof parsed.flags.token === "string" ? parsed.flags.token : process.env.MDOCS_BRIDGE_TOKEN || void 0,
|
|
13992
|
+
requestToken: Boolean(parsed.flags["request-token"] || parsed.flags.pair),
|
|
13993
|
+
pairingTimeoutMs: typeof parsed.flags["pairing-timeout-ms"] === "string" ? Number(parsed.flags["pairing-timeout-ms"]) : void 0
|
|
13933
13994
|
});
|
|
13934
13995
|
return;
|
|
13935
13996
|
}
|
|
@@ -14118,10 +14179,12 @@ Commands:
|
|
|
14118
14179
|
remote events|history|restore Poll events, list commits, restore snapshots
|
|
14119
14180
|
remote library|create-folder|update-folder|move-root|invite-folder
|
|
14120
14181
|
Organize the joined project library
|
|
14182
|
+
bridge --workspace <id> --root . --url <base-url> --request-token
|
|
14183
|
+
Request human approval, then sync an
|
|
14184
|
+
approved local root with the workspace
|
|
14121
14185
|
bridge --workspace <id> --root . --url <base-url> --token <bridge-token>
|
|
14122
14186
|
Sync an approved local root with the workspace
|
|
14123
|
-
(
|
|
14124
|
-
dialog, or MDOCS_BRIDGE_TOKEN)
|
|
14187
|
+
(or set MDOCS_BRIDGE_TOKEN)
|
|
14125
14188
|
bridge --claim <token> --root . --canonical-prefix prompts --replica-prefix packages/agent/prompts
|
|
14126
14189
|
Claim an existing repo path as a Magic-canonical source mapping
|
|
14127
14190
|
doctor --json Validate sidecar mappings
|
package/package.json
CHANGED