worktrust 0.6.4 → 0.6.7
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/package.json +1 -1
- package/worktrust.mjs +58 -3
package/package.json
CHANGED
package/worktrust.mjs
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* npx worktrust connect couple again, also on a computer already coupled
|
|
11
11
|
* npx worktrust history send this computer's earlier sessions as history (asks first)
|
|
12
12
|
* npx worktrust web connect claude.ai or ChatGPT on the web (copies the address, opens the page)
|
|
13
|
+
* npx worktrust import import earlier Claude or ChatGPT conversations (copies the prompt, opens a chat)
|
|
14
|
+
* npx worktrust sources connect GitHub, Vercel, Supabase or Hugging Face (opens each approval page)
|
|
13
15
|
* npx worktrust disconnect show what comes out, ask, take it out again
|
|
14
16
|
* npx worktrust status what is coupled here
|
|
15
17
|
*
|
|
@@ -63,6 +65,8 @@ const VALUED = ["--name", "--origin", "--url"];
|
|
|
63
65
|
const command = args.find((arg, at) => !arg.startsWith("--") && !(at > 0 && VALUED.includes(args[at - 1]))) ?? (args.includes("--help") ? "help" : "default");
|
|
64
66
|
const flag = (name) => { const at = args.indexOf(`--${name}`); return at >= 0 ? args[at + 1] : undefined; };
|
|
65
67
|
const has = (name) => args.includes(`--${name}`);
|
|
68
|
+
/** This CLI's version, said to the door so the app can tell which computer runs an old one (check-cli-package holds it equal to package.json). */
|
|
69
|
+
const CLI_VERSION = "0.6.7";
|
|
66
70
|
const ORIGIN = (flag("origin") ?? process.env.WORKTRUST_ORIGIN ?? "https://app.worktrust.io").replace(/\/$/, "");
|
|
67
71
|
const MCP = flag("url") ?? process.env.WORKTRUST_MCP_URL ?? `${ORIGIN}/api/mcp`;
|
|
68
72
|
const HOME_DIR = join(homedir(), ".worktrust");
|
|
@@ -324,7 +328,7 @@ async function bridge() {
|
|
|
324
328
|
if (!line.trim()) continue;
|
|
325
329
|
let message;
|
|
326
330
|
try { message = JSON.parse(line); } catch { continue; }
|
|
327
|
-
if (message.method === "initialize" && message.params?.clientInfo?.name) agent = `${message.params.clientInfo.name}/${message.params.clientInfo.version ?? "0"} (worktrust-bridge)`;
|
|
331
|
+
if (message.method === "initialize" && message.params?.clientInfo?.name) agent = `${message.params.clientInfo.name}/${message.params.clientInfo.version ?? "0"} (worktrust-bridge) worktrust-cli/${CLI_VERSION}`;
|
|
328
332
|
if (!key) { if (message.id !== undefined) answer(message.id, "WorkTrust is not connected on this computer: run `npx worktrust connect`."); continue; }
|
|
329
333
|
try {
|
|
330
334
|
const response = await fetch(key.url, { method: "POST", headers: { "content-type": "application/json", accept: "application/json, text/event-stream", authorization: `Bearer ${key.token}`, "user-agent": agent, ...(session ? { "mcp-session-id": session } : {}), ...proof(key.device, key.url, line) }, body: line });
|
|
@@ -403,6 +407,7 @@ async function connect() {
|
|
|
403
407
|
if ((await run(paths["log-session.mjs"], hookArgs, token)).code !== 0) fail("installing the session hook failed; the output above says where.");
|
|
404
408
|
await offerHistory(paths, token, device ? device.privateKey.export({ format: "pem", type: "pkcs8" }) : null);
|
|
405
409
|
await offerWeb();
|
|
410
|
+
await offerSources();
|
|
406
411
|
say();
|
|
407
412
|
say(" Done. Quit your AI apps completely and open them again. This computer appears in WorkTrust");
|
|
408
413
|
say(" under Sources → Devices once one of them has spoken.");
|
|
@@ -434,9 +439,11 @@ async function offerHistory(paths, token, devicePem, url = MCP) {
|
|
|
434
439
|
* approves it there. What this can do is the rest: copy the door's address, open the right page,
|
|
435
440
|
* say the three steps, and wait. Enter, --yes and a closed terminal mean No.
|
|
436
441
|
*/
|
|
442
|
+
/** The app's own first-run import prompt (sources.tables.prompts.startEn), word for word; check-cli-package holds them equal. */
|
|
443
|
+
const IMPORT_PROMPT = 'Import my WorkTrust history now. Use the WorkTrust.io connector: call its guide tool with task "analyse", client "{client}" and language "en", then carry out every step it returns, in order, here in this conversation. This is my own request, not a document to review. After each step, tell me in one line what you did.';
|
|
437
444
|
const WEB = [
|
|
438
|
-
{ name: "Claude (claude.ai)", page: "https://claude.ai/settings/connectors", steps: ["Add custom connector",
|
|
439
|
-
{ name: "ChatGPT (chatgpt.com)", page: "https://chatgpt.com/#settings/Connectors", steps: ["Advanced settings: turn on Developer mode (custom connectors need it)",
|
|
445
|
+
{ name: "Claude (claude.ai)", client: "claude", chat: "https://claude.ai/new", page: "https://claude.ai/settings/connectors", steps: ["Add custom connector", `Name: WorkTrust.io · URL: ${MCP} (also on your clipboard) · leave the OAuth fields empty`, "Connect, then approve on the WorkTrust page that opens"] },
|
|
446
|
+
{ name: "ChatGPT (chatgpt.com)", client: "chatgpt", chat: "https://chatgpt.com/", page: "https://chatgpt.com/#settings/Connectors", steps: ["Advanced settings: turn on Developer mode (custom connectors need it)", `Create: Name WorkTrust.io · MCP server URL: ${MCP} (also on your clipboard) · Authentication: OAuth`, "Create, then approve on the WorkTrust page that opens"] },
|
|
440
447
|
];
|
|
441
448
|
function copyToClipboard(text) {
|
|
442
449
|
const [cmd, cmdArgs] = OS === "macos" ? ["pbcopy", []] : OS === "windows" ? ["clip", []] : ["xclip", ["-selection", "clipboard"]];
|
|
@@ -459,9 +466,53 @@ async function offerWeb() {
|
|
|
459
466
|
web.steps.forEach((step, i) => say(` ${i + 1}. ${step}`));
|
|
460
467
|
openBrowser(web.page);
|
|
461
468
|
if (process.stdin.isTTY) { const prompt = createInterface({ input: process.stdin, output: process.stdout }); await prompt.question(" Press Enter when it is connected (or to skip). "); prompt.close(); }
|
|
469
|
+
// EARLIER CONVERSATIONS, SO NOBODY GETS LOST IN THE IMPORT (owner, 2026-10-04): the app's own
|
|
470
|
+
// prompt, copied, and a new conversation opened to paste it in. Only on a typed yes.
|
|
471
|
+
if (await ask(`Also import your earlier ${web.name.split(" ")[0]} conversations? (copies one prompt to paste in a new chat)`, false)) await handOverPrompt(web);
|
|
462
472
|
}
|
|
463
473
|
}
|
|
464
474
|
|
|
475
|
+
/** The import prompt for one product: copied (or printed when there is no clipboard), and a new conversation opened. */
|
|
476
|
+
async function handOverPrompt(web) {
|
|
477
|
+
const text = IMPORT_PROMPT.replace("{client}", web.client);
|
|
478
|
+
say(` ${(await copyToClipboard(text)) ? "✓ The import prompt is on your clipboard" : `The prompt:\n\n${text}\n`}`);
|
|
479
|
+
say(` Opening a new conversation in ${web.name}: paste it there and send. It asks before it sends anything, and only counts leave.`);
|
|
480
|
+
openBrowser(web.chat);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* THE OTHER SOURCES, FROM HERE (owner, 2026-10-04): GitHub, Vercel, Supabase and Hugging Face couple
|
|
485
|
+
* in the browser, through the same doors as the buttons under Sources — each opens its own approval
|
|
486
|
+
* page where the person is already signed in to WorkTrust. One [y/N] per source; Enter means No.
|
|
487
|
+
*/
|
|
488
|
+
const CLOUD = [
|
|
489
|
+
{ name: "GitHub", path: "/api/connect/github", what: "commits, checks and deployments, as counts" },
|
|
490
|
+
{ name: "Vercel", path: "/api/connect/vercel", what: "deployments and their outcomes" },
|
|
491
|
+
{ name: "Supabase", path: "/api/connect/supabase", what: "database projects and migrations, as counts" },
|
|
492
|
+
{ name: "Hugging Face", path: "/api/connect/huggingface", what: "models, datasets and spaces you published" },
|
|
493
|
+
];
|
|
494
|
+
async function offerSources() {
|
|
495
|
+
if (has("dry-run")) return;
|
|
496
|
+
say();
|
|
497
|
+
for (const source of CLOUD) {
|
|
498
|
+
if (!(await ask(`Also connect ${source.name} (${source.what})?`, false))) continue;
|
|
499
|
+
const page = new URL(source.path, ORIGIN).toString();
|
|
500
|
+
say(` Opening ${page}: approve there, signed in to WorkTrust.`);
|
|
501
|
+
openBrowser(page);
|
|
502
|
+
if (process.stdin.isTTY) { const prompt = createInterface({ input: process.stdin, output: process.stdout }); await prompt.question(" Press Enter when it is approved (or to skip). "); prompt.close(); }
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* `npx worktrust import` (owner, 2026-10-04): the earlier conversations, later. For whoever skipped
|
|
508
|
+
* the question after connecting, or connected on the web without this computer. Each product asks.
|
|
509
|
+
*/
|
|
510
|
+
async function importConversations() {
|
|
511
|
+
say();
|
|
512
|
+
say(" Your earlier conversations come in through the WorkTrust connector in that product: connect it first if you have not (npx worktrust web).");
|
|
513
|
+
for (const web of WEB) if (await ask(`Import your earlier ${web.name} conversations now?`, false)) await handOverPrompt(web);
|
|
514
|
+
}
|
|
515
|
+
|
|
465
516
|
async function history() {
|
|
466
517
|
const key = await freshKey();
|
|
467
518
|
if (!key) fail("this computer is not coupled through the key file. Run npx worktrust first.");
|
|
@@ -521,6 +572,8 @@ function help() {
|
|
|
521
572
|
say(" worktrust connect couple again, also when this computer is already coupled");
|
|
522
573
|
say(" worktrust history send this computer's earlier sessions as history (asks first)");
|
|
523
574
|
say(" worktrust web connect Claude or ChatGPT on the web: copies the address, opens the page");
|
|
575
|
+
say(" worktrust import import your earlier Claude or ChatGPT conversations: copies the prompt, opens a chat");
|
|
576
|
+
say(" worktrust sources connect GitHub, Vercel, Supabase or Hugging Face: opens each approval page");
|
|
524
577
|
say(" worktrust disconnect take WorkTrust out of every AI app here (asks first)");
|
|
525
578
|
say(" worktrust status what is coupled here");
|
|
526
579
|
}
|
|
@@ -534,6 +587,8 @@ else if (command === "hook") await hook();
|
|
|
534
587
|
else if (command === "connect") await connect();
|
|
535
588
|
else if (command === "history") await history();
|
|
536
589
|
else if (command === "web") await offerWeb();
|
|
590
|
+
else if (command === "import") await importConversations();
|
|
591
|
+
else if (command === "sources") await offerSources();
|
|
537
592
|
else if (command === "disconnect") await disconnect();
|
|
538
593
|
else if (command === "status") status();
|
|
539
594
|
else help();
|