drafted 1.19.26 → 1.19.27
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/mcp/server.mjs +47 -46
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -2106,6 +2106,51 @@ function desktopAppBinary() {
|
|
|
2106
2106
|
return null; // e.g. Linux — no desktop app → device-code fallback
|
|
2107
2107
|
}
|
|
2108
2108
|
|
|
2109
|
+
/**
|
|
2110
|
+
* The answer to "am I signed in?", which is a question about the MACHINE, not this
|
|
2111
|
+
* process. Two things went wrong before this existed, and they are the same mistake:
|
|
2112
|
+
*
|
|
2113
|
+
* - ~/.drafted/auth.json could be missing while the in-process session was fine. The
|
|
2114
|
+
* desktop's credential burn deletes it on purpose, so `login` answered
|
|
2115
|
+
* already_authenticated — truthfully, and uselessly — while every other reader on the
|
|
2116
|
+
* machine stayed signed out. Restore it from the live session.
|
|
2117
|
+
* - The DESKTOP app could be signed out, which is what actually decides whether an agent
|
|
2118
|
+
* asking for a human reaches anybody: its focus listener needs desktop.json. An agent
|
|
2119
|
+
* must never MINT that credential (origin='browser' is the class that may approve
|
|
2120
|
+
* actions), but opening the app's sign-in window is this tool's documented job — and it
|
|
2121
|
+
* usually completes with NO interaction, because the shared cookie store still holds a
|
|
2122
|
+
* valid login.
|
|
2123
|
+
*/
|
|
2124
|
+
async function alreadyAuthenticated(me, sessionId) {
|
|
2125
|
+
const out = { status: 'already_authenticated', userId: me.userId, email: me.userEmail, org: me.currentOrg?.name };
|
|
2126
|
+
if (!getBootstrapSessionId()) {
|
|
2127
|
+
try {
|
|
2128
|
+
persistAuthSession({ sessionId, userId: me.userId, orgId: me.currentOrg?.id });
|
|
2129
|
+
out.restoredAuthFile = true;
|
|
2130
|
+
out.note = 'This session was signed in but ~/.drafted/auth.json was missing, so other readers on this machine (the desktop app, the CLI) were not. Rewrote it from the live session.';
|
|
2131
|
+
} catch { /* read-only home: report the truth rather than throwing */ }
|
|
2132
|
+
}
|
|
2133
|
+
const bin = desktopAppBinary();
|
|
2134
|
+
if (!bin) return out; // no app here: saying anything about it is noise
|
|
2135
|
+
if (!existsSync(DESKTOP_SESSION_FILE)) {
|
|
2136
|
+
if (await launchDesktopSignin()) {
|
|
2137
|
+
out.openedDesktopSignin = true;
|
|
2138
|
+
// Wait for the result rather than reporting an optimistic one — answering before it
|
|
2139
|
+
// lands is the same class of lie this whole helper exists to stop.
|
|
2140
|
+
for (let i = 0; i < 20 && !existsSync(DESKTOP_SESSION_FILE); i++) {
|
|
2141
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
out.desktopSignedIn = existsSync(DESKTOP_SESSION_FILE);
|
|
2146
|
+
if (out.openedDesktopSignin) {
|
|
2147
|
+
out.desktopNote = out.desktopSignedIn
|
|
2148
|
+
? 'The desktop app was signed out; opened its sign-in window and it completed on its own from the existing browser session.'
|
|
2149
|
+
: 'The desktop app is signed out and its sign-in window is open — it needs one approval there. Until then it holds no session, so an agent asking for attention cannot reach this machine.';
|
|
2150
|
+
}
|
|
2151
|
+
return out;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2109
2154
|
async function launchDesktopSignin() {
|
|
2110
2155
|
const bin = desktopAppBinary();
|
|
2111
2156
|
if (!bin) return false;
|
|
@@ -2186,7 +2231,7 @@ if (!isRemote) tool('auth', 'Sign in to Drafted.\n\n`action=get_link` ALWAYS ret
|
|
|
2186
2231
|
await cloneSession();
|
|
2187
2232
|
connectAgentWs();
|
|
2188
2233
|
}
|
|
2189
|
-
return ok(
|
|
2234
|
+
return ok(await alreadyAuthenticated(me, existing));
|
|
2190
2235
|
}
|
|
2191
2236
|
} catch { /* stale session — continue to sign-in */ }
|
|
2192
2237
|
}
|
|
@@ -2232,51 +2277,7 @@ if (!isRemote) tool('auth', 'Sign in to Drafted.\n\n`action=get_link` ALWAYS ret
|
|
|
2232
2277
|
// The desktop's focus listener is one of those readers, so an agent asking
|
|
2233
2278
|
// for a human reached nobody and the tool that exists to fix it reported
|
|
2234
2279
|
// success.
|
|
2235
|
-
|
|
2236
|
-
if (!getBootstrapSessionId()) {
|
|
2237
|
-
try {
|
|
2238
|
-
persistAuthSession({ sessionId: existing, userId: me.userId, orgId: me.currentOrg?.id });
|
|
2239
|
-
restoredAuthFile = true;
|
|
2240
|
-
} catch { /* read-only home: report the truth below rather than throwing */ }
|
|
2241
|
-
}
|
|
2242
|
-
// The DESKTOP's own browser credential is a separate file, and an agent
|
|
2243
|
-
// cannot mint one — it is the origin='browser' class that may approve
|
|
2244
|
-
// actions, which is exactly what the two-credential split protects. But
|
|
2245
|
-
// "cannot mint it" is not "cannot ask for it": opening the app's sign-in
|
|
2246
|
-
// window is this tool's documented job, and the window usually completes
|
|
2247
|
-
// with no interaction at all because the shared cookie store still holds a
|
|
2248
|
-
// valid login. Short-circuiting on the agent session skipped that entirely,
|
|
2249
|
-
// so `login` reported success while the app stayed signed out and every
|
|
2250
|
-
// agent that pinged the human reached nobody.
|
|
2251
|
-
let openedDesktopSignin = false;
|
|
2252
|
-
if (desktopAppBinary() && !existsSync(DESKTOP_SESSION_FILE)) {
|
|
2253
|
-
openedDesktopSignin = await launchDesktopSignin();
|
|
2254
|
-
if (openedDesktopSignin) {
|
|
2255
|
-
// Give the app a moment to re-capture the cookie so the caller can act
|
|
2256
|
-
// on a true answer rather than an optimistic one.
|
|
2257
|
-
for (let i = 0; i < 20 && !existsSync(DESKTOP_SESSION_FILE); i++) {
|
|
2258
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
const desktopSignedIn = !desktopAppBinary() ? null : existsSync(DESKTOP_SESSION_FILE);
|
|
2263
|
-
return ok({
|
|
2264
|
-
status: 'already_authenticated',
|
|
2265
|
-
userId: me.userId,
|
|
2266
|
-
email: me.userEmail,
|
|
2267
|
-
org: me.currentOrg?.name,
|
|
2268
|
-
...(restoredAuthFile ? {
|
|
2269
|
-
restoredAuthFile: true,
|
|
2270
|
-
note: 'This session was signed in but ~/.drafted/auth.json was missing, so other readers on this machine (the desktop app, the CLI) were not. Rewrote it from the live session.',
|
|
2271
|
-
} : {}),
|
|
2272
|
-
...(desktopSignedIn === null ? {} : { desktopSignedIn }),
|
|
2273
|
-
...(openedDesktopSignin ? {
|
|
2274
|
-
openedDesktopSignin: true,
|
|
2275
|
-
desktopNote: desktopSignedIn
|
|
2276
|
-
? 'The desktop app was signed out; opened its sign-in window and it completed on its own from the existing browser session.'
|
|
2277
|
-
: 'The desktop app is signed out and its sign-in window is open — it needs one approval there. Until then it holds no session, so an agent asking for attention cannot reach this machine.',
|
|
2278
|
-
} : {}),
|
|
2279
|
-
});
|
|
2280
|
+
return ok(await alreadyAuthenticated(me, existing));
|
|
2280
2281
|
}
|
|
2281
2282
|
} catch { /* session invalid, proceed with login */ }
|
|
2282
2283
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.27",
|
|
4
4
|
"description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|