@thinkingai/ae-cli 6.0.48-workbuddy.1 → 6.0.48-workbuddy.2

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.
@@ -262,11 +262,93 @@ function sleep(ms) {
262
262
  return new Promise((resolve) => setTimeout(resolve, ms));
263
263
  }
264
264
 
265
+ // src/integrations/workbuddy/auth.ts
266
+ import { setTimeout as delay } from "timers/promises";
267
+
265
268
  // src/integrations/workbuddy/host-page.ts
266
269
  import { randomBytes } from "crypto";
267
270
  import fs from "fs";
268
271
  import { createServer } from "http";
269
272
  import { fileURLToPath } from "url";
273
+
274
+ // src/integrations/workbuddy/entry-page.ts
275
+ function renderWorkBuddyEntryPage(sessionPath, nonce) {
276
+ return `<!doctype html>
277
+ <html lang="zh-CN">
278
+ <head>
279
+ <meta charset="utf-8">
280
+ <meta name="viewport" content="width=device-width, initial-scale=1">
281
+ <title>ThinkingAI \xD7 WorkBuddy</title>
282
+ <style nonce="${nonce}">
283
+ * { box-sizing: border-box; }
284
+ body { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 48px 24px; color: #111d35; font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; background: radial-gradient(circle at 18% 7%, rgba(64,130,255,.09), transparent 29%), radial-gradient(circle at 86% 92%, rgba(37,204,173,.08), transparent 26%), #f4f8fd; }
285
+ .shell { width: min(940px, 100%); padding: 48px 52px 32px; border: 1px solid #dce5f1; border-radius: 28px; background: #fff; box-shadow: 0 24px 70px rgba(35,67,115,.13); }
286
+ .brands { display: flex; align-items: center; justify-content: center; gap: 22px; min-height: 72px; }
287
+ .thinkingai { width: 256px; height: auto; }
288
+ .workbuddy { width: 142px; height: auto; }
289
+ .dots { display: flex; align-items: center; gap: 7px; padding: 0 2px; }
290
+ .dots i { width: 7px; height: 7px; border-radius: 50%; background: #9aa7ba; animation: pulse 1.4s ease-in-out infinite; }
291
+ .dots i:nth-child(2) { animation-delay: .18s; }
292
+ .dots i:nth-child(3) { animation-delay: .36s; }
293
+ @keyframes pulse { 0%, 65%, 100% { opacity: .36; transform: scale(.82); } 30% { opacity: 1; transform: scale(1.18); } }
294
+ h1 { margin: 30px 0 8px; text-align: center; font-size: 38px; line-height: 1.25; letter-spacing: -.8px; }
295
+ .routes { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 34px; }
296
+ .route { position: relative; display: flex; min-height: 286px; flex-direction: column; padding: 28px; border: 1.5px solid #d8e2ef; border-radius: 20px; background: #fff; }
297
+ .route.primary { border-color: #8db9ff; background: linear-gradient(150deg, #f4f8ff, #eef6ff); box-shadow: 0 12px 30px rgba(22,115,243,.08); }
298
+ .badge { position: absolute; top: 20px; right: 20px; padding: 6px 10px; border-radius: 999px; color: #1368dd; background: #e4efff; font-size: 12px; font-weight: 700; }
299
+ .secondary .badge { color: #5d6b82; background: #eef2f7; }
300
+ .icon { display: grid; place-items: center; width: 48px; height: 48px; margin-bottom: 24px; border-radius: 14px; color: #fff; background: #1677ff; box-shadow: 0 9px 20px rgba(22,119,255,.2); }
301
+ .secondary .icon { color: #315174; background: #edf3fa; box-shadow: none; }
302
+ .icon svg { width: 25px; height: 25px; }
303
+ .route h2 { margin: 0 0 10px; font-size: 22px; letter-spacing: -.2px; }
304
+ .route p { margin: 0 0 16px; color: #64738c; font-size: 15px; line-height: 1.72; }
305
+ .route .handoff-note { color: #7b899e; font-size: 13px; }
306
+ .action { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 50px; margin-top: auto; border: 1px solid #c8d6e8; border-radius: 12px; color: #263852; background: #fff; font-size: 16px; font-weight: 700; text-decoration: none; }
307
+ .primary .action { border-color: #1677ff; color: #fff; background: #1677ff; }
308
+ .action:hover { background: #f3f7fc; }
309
+ .primary .action:hover { background: #0869ed; }
310
+ .action:focus-visible { outline: 3px solid #8db9ff; outline-offset: 3px; }
311
+ .note { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 24px 0 0; color: #7b899e; font-size: 13px; }
312
+ .note svg { width: 16px; height: 16px; flex: none; }
313
+ footer { margin-top: 22px; padding-top: 22px; border-top: 1px solid #edf1f6; color: #8995a8; text-align: center; font-size: 13px; }
314
+ @media (prefers-reduced-motion: reduce) { .dots i { animation: none; opacity: .65; } }
315
+ @media (max-width: 740px) { body { padding: 0; background: #fff; } .shell { min-height: 100vh; padding: 32px 20px 26px; border: 0; border-radius: 0; box-shadow: none; } .thinkingai { width: 188px; } .workbuddy { width: 106px; } .brands { gap: 12px; } h1 { font-size: 30px; } .routes { grid-template-columns: 1fr; } .route { min-height: 246px; } }
316
+ @media (max-width: 400px) { .thinkingai { width: 160px; } .workbuddy { width: 90px; } .dots { gap: 4px; } .dots i { width: 5px; height: 5px; } }
317
+ </style>
318
+ </head>
319
+ <body>
320
+ <main class="shell">
321
+ <div class="brands" aria-label="ThinkingAI \u4E0E WorkBuddy">
322
+ <img class="thinkingai" src="${sessionPath}thinkingai.svg" alt="ThinkingAI">
323
+ <span class="dots" aria-hidden="true"><i></i><i></i><i></i></span>
324
+ <img class="workbuddy" src="${sessionPath}workbuddy.png" alt="WorkBuddy">
325
+ </div>
326
+ <h1>\u9009\u62E9\u4F7F\u7528\u65B9\u5F0F</h1>
327
+ <section class="routes" aria-label="\u4F7F\u7528\u65B9\u5F0F">
328
+ <article class="route primary">
329
+ <span class="badge">\u63A8\u8350\u65B0\u7528\u6237</span>
330
+ <div class="icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18M12 3a15 15 0 0 0 0 18"/></svg></div>
331
+ <h2>\u524D\u5F80 ThinkingAI \u5B98\u7F51</h2>
332
+ <p>\u9996\u6B21\u4F7F\u7528 ThinkingAI\uFF0C\u6216\u5E0C\u671B\u5728\u5B98\u7F51\u5B8C\u6210\u6CE8\u518C\u3001\u5F00\u901A\u53CA\u540E\u7EED\u4F7F\u7528\u3002</p>
333
+ <p class="handoff-note">\u5C06\u79BB\u5F00 WorkBuddy\uFF0C\u524D\u5F80\u5B98\u7F51\u7EE7\u7EED\u4F7F\u7528\u3002</p>
334
+ <a class="action" href="${sessionPath}website">\u524D\u5F80\u5B98\u7F51</a>
335
+ </article>
336
+ <article class="route secondary">
337
+ <span class="badge">\u5DF2\u6709 AE \u7528\u6237</span>
338
+ <div class="icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.5.5l2-2a5 5 0 0 0-7-7l-1.1 1.1"/><path d="M14 11a5 5 0 0 0-7.5-.5l-2 2a5 5 0 0 0 7 7l1.1-1.1"/></svg></div>
339
+ <h2>\u8FDE\u63A5\u5DF2\u6709 AE \u73AF\u5883</h2>
340
+ <p>\u5DF2\u7ECF\u4F7F\u7528 ae-cli \u6216\u62E5\u6709 AE Host\uFF0C\u5728 WorkBuddy \u4E2D\u7EE7\u7EED\u5B8C\u6210\u8FDE\u63A5\u3002</p>
341
+ <a class="action" href="${sessionPath}host">\u7EE7\u7EED\u8FDE\u63A5</a>
342
+ </article>
343
+ </section>
344
+ <p class="note"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/></svg>\u8D26\u53F7\u5BC6\u7801\u53EA\u4F1A\u5728 AE \u7EDF\u4E00\u767B\u5F55\u9875\u8F93\u5165\uFF1B\u89E3\u7ED1\u540E\u53EF\u4EE5\u91CD\u65B0\u9009\u62E9\u4F7F\u7528\u65B9\u5F0F</p>
345
+ <footer>\u7531 WorkBuddy \xB7 ae-cli \u53D1\u8D77</footer>
346
+ </main>
347
+ </body>
348
+ </html>`;
349
+ }
350
+
351
+ // src/integrations/workbuddy/host-page.ts
270
352
  var LOOPBACK_ADDRESS = "127.0.0.1";
271
353
  var MAX_REQUEST_BYTES = 4096;
272
354
  function validateWorkBuddyHost(input) {
@@ -316,6 +398,8 @@ function renderWorkBuddyHostPage(hosts, sessionPath, nonce) {
316
398
  @keyframes connectionPulse { 0%, 70%, 100% { opacity: .2; transform: translateY(0) scale(.82); } 35% { opacity: 1; transform: translateY(-1px) scale(1); } }
317
399
  h1 { margin: 0; text-align: center; font-size: 30px; line-height: 1.25; letter-spacing: -.025em; }
318
400
  .subtitle { margin: 7px 0 22px; text-align: center; color: #62708a; font-size: 16px; }
401
+ .back { display: inline-block; margin-bottom: 18px; color: #62708a; font-size: 13px; text-decoration: none; }
402
+ .back:hover { color: #0878f9; }
319
403
  fieldset { margin: 0; padding: 0; border: 0; }
320
404
  legend, .field-label { display: block; margin-bottom: 10px; color: #18243c; font-size: 15px; font-weight: 700; }
321
405
  .host-list { display: grid; gap: 8px; max-height: 188px; overflow: auto; }
@@ -353,6 +437,7 @@ function renderWorkBuddyHostPage(hosts, sessionPath, nonce) {
353
437
  </head>
354
438
  <body>
355
439
  <main class="card">
440
+ <a class="back" href="${sessionPath}">\u2190 \u8FD4\u56DE\u9009\u62E9\u4F7F\u7528\u65B9\u5F0F</a>
356
441
  <header>
357
442
  <div class="brands" aria-label="ThinkingAI \u4E0E WorkBuddy">
358
443
  <img class="thinkingai" src="${sessionPath}thinkingai.svg" alt="ThinkingAI">
@@ -452,13 +537,29 @@ async function startWorkBuddyHostPage(options = {}) {
452
537
  const selection = new Promise((resolve) => {
453
538
  resolveSelection = resolve;
454
539
  });
540
+ let resolveWebsiteHandoff = () => {
541
+ };
542
+ const websiteHandoff = new Promise((resolve) => {
543
+ resolveWebsiteHandoff = resolve;
544
+ });
455
545
  const server = createServer(async (request, response) => {
456
546
  setSecurityHeaders(response, nonce);
457
547
  const requestUrl = new URL(request.url ?? "/", `http://${LOOPBACK_ADDRESS}`);
458
548
  if (request.method === "GET" && requestUrl.pathname === sessionPath) {
549
+ respond(response, 200, "text/html; charset=utf-8", renderWorkBuddyEntryPage(sessionPath, nonce));
550
+ return;
551
+ }
552
+ if (request.method === "GET" && requestUrl.pathname === `${sessionPath}host`) {
459
553
  respond(response, 200, "text/html; charset=utf-8", renderWorkBuddyHostPage(hosts, sessionPath, nonce));
460
554
  return;
461
555
  }
556
+ if (request.method === "GET" && requestUrl.pathname === `${sessionPath}website`) {
557
+ response.once("finish", resolveWebsiteHandoff);
558
+ response.statusCode = 302;
559
+ response.setHeader("Location", "https://www.thinkingai.cn/workbuddy/");
560
+ response.end();
561
+ return;
562
+ }
462
563
  if (request.method === "GET" && requestUrl.pathname === `${sessionPath}thinkingai.svg`) {
463
564
  respond(response, 200, "image/svg+xml", assets.thinkingai);
464
565
  return;
@@ -489,6 +590,7 @@ async function startWorkBuddyHostPage(options = {}) {
489
590
  return {
490
591
  url: `http://${LOOPBACK_ADDRESS}:${address.port}${sessionPath}`,
491
592
  selection,
593
+ websiteHandoff,
492
594
  close: () => closeServer(server)
493
595
  };
494
596
  }
@@ -594,12 +696,17 @@ function registerWorkBuddyAuth(auth) {
594
696
  process.stderr.write(`[ae-cli] WorkBuddy host selection:
595
697
  ${page.url}
596
698
  `);
597
- const selected = await Promise.race([
598
- page.selection.then(() => true),
599
- waitForTerminationSignal().then(() => false)
699
+ const outcome = await Promise.race([
700
+ page.selection.then(() => "selected"),
701
+ page.websiteHandoff.then(() => "website"),
702
+ waitForTerminationSignal().then(() => "terminated")
600
703
  ]);
601
704
  await page.close();
602
- if (!selected) process.exitCode = 1;
705
+ if (outcome === "website") {
706
+ await delay(3e3);
707
+ process.stderr.write("[ae-cli] Website selected; WorkBuddy authentication stopped.\n");
708
+ }
709
+ if (outcome !== "selected") process.exitCode = 1;
603
710
  });
604
711
  }
605
712
  function waitForTerminationSignal() {
package/dist/index.js CHANGED
@@ -2389,7 +2389,7 @@ async function loadCommands() {
2389
2389
  }
2390
2390
  async function registerAuthCommands() {
2391
2391
  try {
2392
- const { registerAuth } = await import("./auth-UA4GLHVX.js");
2392
+ const { registerAuth } = await import("./auth-HK246OGX.js");
2393
2393
  registerAuth(program);
2394
2394
  } catch {
2395
2395
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkingai/ae-cli",
3
- "version": "6.0.48-workbuddy.1",
3
+ "version": "6.0.48-workbuddy.2",
4
4
  "description": "CLI tool for ThinkingAI (AE) analytics platform",
5
5
  "type": "module",
6
6
  "bin": {