@mulmoclaude/core 0.23.0 → 0.24.0

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.
Files changed (53) hide show
  1. package/assets/helps/collection-skills.md +39 -7
  2. package/assets/helps/custom-view.md +13 -9
  3. package/assets/skills-preset/mc-zenn/SKILL.md +31 -0
  4. package/dist/collection/core/completion.d.ts +18 -0
  5. package/dist/collection/core/deriveAll.d.ts +14 -9
  6. package/dist/collection/core/schema.d.ts +9 -4
  7. package/dist/collection/core/schemaZ.d.ts +97 -43
  8. package/dist/collection/index.cjs +2 -1
  9. package/dist/collection/index.cjs.map +1 -1
  10. package/dist/collection/index.d.ts +1 -0
  11. package/dist/collection/index.js +2 -2
  12. package/dist/collection/index.js.map +1 -1
  13. package/dist/collection/registry/server/index.cjs +1 -1
  14. package/dist/collection/registry/server/index.js +1 -1
  15. package/dist/collection/server/csvQuery.d.ts +13 -5
  16. package/dist/collection/server/csvStore.d.ts +2 -0
  17. package/dist/collection/server/index.cjs +4 -2
  18. package/dist/collection/server/index.d.ts +2 -1
  19. package/dist/collection/server/index.js +3 -3
  20. package/dist/collection/server/jsonlQuery.d.ts +4 -0
  21. package/dist/collection-watchers/index.cjs +5 -14
  22. package/dist/collection-watchers/index.cjs.map +1 -1
  23. package/dist/collection-watchers/index.js +2 -11
  24. package/dist/collection-watchers/index.js.map +1 -1
  25. package/dist/collection-watchers/reconciler.d.ts +2 -4
  26. package/dist/feeds/index.cjs +2 -2
  27. package/dist/feeds/index.js +2 -2
  28. package/dist/feeds/server/index.cjs +3 -3
  29. package/dist/feeds/server/index.js +3 -3
  30. package/dist/google/auth.d.ts +10 -1
  31. package/dist/google/authFlow.d.ts +1 -0
  32. package/dist/google/index.cjs +79 -38
  33. package/dist/google/index.cjs.map +1 -1
  34. package/dist/google/index.d.ts +1 -1
  35. package/dist/google/index.js +78 -39
  36. package/dist/google/index.js.map +1 -1
  37. package/dist/{ingestTypes-B-dXxUF9.js → ingestTypes-CFEgTItj.js} +2 -2
  38. package/dist/{ingestTypes-B-dXxUF9.js.map → ingestTypes-CFEgTItj.js.map} +1 -1
  39. package/dist/{ingestTypes-Cev9q77C.cjs → ingestTypes-Stc7iQyA.cjs} +2 -2
  40. package/dist/{ingestTypes-Cev9q77C.cjs.map → ingestTypes-Stc7iQyA.cjs.map} +1 -1
  41. package/dist/{promptSafety-rDWA9_JS.js → promptSafety-BLUcImzd.js} +54 -26
  42. package/dist/promptSafety-BLUcImzd.js.map +1 -0
  43. package/dist/{promptSafety-DRd15gQ6.cjs → promptSafety-DI_1Rvhk.cjs} +59 -25
  44. package/dist/promptSafety-DI_1Rvhk.cjs.map +1 -0
  45. package/dist/{server--FgDORd3.js → server-BpEo0FOd.js} +233 -57
  46. package/dist/server-BpEo0FOd.js.map +1 -0
  47. package/dist/{server-Q7ld-FlZ.cjs → server-CkysfLh4.cjs} +244 -56
  48. package/dist/server-CkysfLh4.cjs.map +1 -0
  49. package/package.json +1 -1
  50. package/dist/promptSafety-DRd15gQ6.cjs.map +0 -1
  51. package/dist/promptSafety-rDWA9_JS.js.map +0 -1
  52. package/dist/server--FgDORd3.js.map +0 -1
  53. package/dist/server-Q7ld-FlZ.cjs.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import { default as http } from 'node:http';
2
2
  import { Credentials } from 'google-auth-library';
3
3
  import { fetchWithTimeout } from './fetch.js';
4
+ import { IssuedVia } from './tokenStore.js';
4
5
  export declare const GOOGLE_CALENDAR_SCOPE = "https://www.googleapis.com/auth/calendar.events";
5
6
  /** Minimal read scope for the calendar list + per-calendar colours.
6
7
  * `calendar.events` already covers reading/writing events on any calendar, but
@@ -19,6 +20,9 @@ export interface AuthorizeGoogleOptions {
19
20
  /** Called with the consent URL; open it in a browser (and/or print it). */
20
21
  onAuthUrl?: (url: string) => void;
21
22
  timeoutMs?: number;
23
+ /** Abort a still-pending consent (a settings-UI restart, an explicit cancel).
24
+ * Rejects the flow with {@link GOOGLE_AUTH_CANCELLED} and closes the loopback. */
25
+ signal?: AbortSignal;
22
26
  }
23
27
  export declare function getGoogleAccessToken(home?: string): Promise<string>;
24
28
  /** The revoke POST, injectable for tests. */
@@ -28,5 +32,10 @@ export type RevokeFetch = typeof fetchWithTimeout;
28
32
  * already consider the token invalid, and keeping the file would leave the
29
33
  * user unable to unlink. */
30
34
  export declare function unlinkGoogle(home?: string, revokeFetch?: RevokeFetch): Promise<void>;
31
- export declare const waitForAuthCode: (server: http.Server, expectedState: string, timeoutMs: number) => Promise<string>;
35
+ /** Reject reason when a pending flow is torn down (a settings-UI restart or an
36
+ * explicit cancel), kept distinct from a real authorization error so callers
37
+ * can treat it as "user changed their mind", not "linking failed". */
38
+ export declare const GOOGLE_AUTH_CANCELLED = "authorization cancelled";
39
+ export declare const waitForAuthCode: (server: http.Server, expectedState: string, timeoutMs: number, signal?: AbortSignal) => Promise<string>;
40
+ export declare const commitLinkedTokens: (tokens: Credentials, issuedVia: IssuedVia, opts: AuthorizeGoogleOptions) => Promise<Credentials>;
32
41
  export declare function authorizeGoogle(opts?: AuthorizeGoogleOptions): Promise<Credentials>;
@@ -7,6 +7,7 @@ export interface GoogleAuthFlow {
7
7
  start: () => Promise<{
8
8
  authUrl: string;
9
9
  }>;
10
+ cancel: () => void;
10
11
  status: () => GoogleAuthFlowStatus;
11
12
  }
12
13
  export declare const createGoogleAuthFlow: (authorize: typeof authorizeGoogle) => GoogleAuthFlow;
@@ -453,29 +453,50 @@ var respondHtml = (res, status, message) => {
453
453
  res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
454
454
  res.end(`<html><body><h3>${message}</h3></body></html>`);
455
455
  };
456
- var waitForAuthCode = (server, expectedState, timeoutMs) => new Promise((resolve, reject) => {
456
+ /** Reject reason when a pending flow is torn down (a settings-UI restart or an
457
+ * explicit cancel), kept distinct from a real authorization error so callers
458
+ * can treat it as "user changed their mind", not "linking failed". */
459
+ var GOOGLE_AUTH_CANCELLED = "authorization cancelled";
460
+ var handleCallbackRequest = (req, res, expectedState, settle) => {
461
+ const url = new URL(req.url ?? "/", "http://127.0.0.1");
462
+ if (url.pathname !== CALLBACK_PATH) {
463
+ res.writeHead(404);
464
+ res.end();
465
+ return;
466
+ }
467
+ if (url.searchParams.get("state") !== expectedState) {
468
+ respondHtml(res, 400, "Invalid authorization callback. You can close this tab.");
469
+ return;
470
+ }
471
+ try {
472
+ const code = authCodeFromCallback(url, expectedState);
473
+ respondHtml(res, 200, "Authorization complete — you can close this tab.");
474
+ settle.resolve(code);
475
+ } catch (err) {
476
+ respondHtml(res, 400, "Authorization failed — see the terminal for details. You can close this tab.");
477
+ settle.reject(err);
478
+ }
479
+ };
480
+ var waitForAuthCode = (server, expectedState, timeoutMs, signal) => new Promise((resolve, reject) => {
457
481
  const timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`authorization timed out after ${timeoutMs / ONE_SECOND_MS}s`)), timeoutMs);
458
- server.on("request", (req, res) => {
459
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
460
- if (url.pathname !== CALLBACK_PATH) {
461
- res.writeHead(404);
462
- res.end();
463
- return;
482
+ const settle = {
483
+ resolve: (code) => {
484
+ clearTimeout(timer);
485
+ resolve(code);
486
+ },
487
+ reject: (err) => {
488
+ clearTimeout(timer);
489
+ reject(err instanceof Error ? err : new Error(String(err)));
464
490
  }
465
- if (url.searchParams.get("state") !== expectedState) {
466
- respondHtml(res, 400, "Invalid authorization callback. You can close this tab.");
491
+ };
492
+ if (signal) {
493
+ if (signal.aborted) {
494
+ settle.reject(/* @__PURE__ */ new Error(GOOGLE_AUTH_CANCELLED));
467
495
  return;
468
496
  }
469
- clearTimeout(timer);
470
- try {
471
- const code = authCodeFromCallback(url, expectedState);
472
- respondHtml(res, 200, "Authorization complete — you can close this tab.");
473
- resolve(code);
474
- } catch (err) {
475
- respondHtml(res, 400, "Authorization failed — see the terminal for details. You can close this tab.");
476
- reject(err);
477
- }
478
- });
497
+ signal.addEventListener("abort", () => settle.reject(/* @__PURE__ */ new Error(GOOGLE_AUTH_CANCELLED)), { once: true });
498
+ }
499
+ server.on("request", (req, res) => handleCallbackRequest(req, res, expectedState, settle));
479
500
  });
480
501
  var buildConsentUrl = (client, codeChallenge, state) => client.generateAuthUrl({
481
502
  access_type: "offline",
@@ -499,7 +520,7 @@ var authorizeWithLocalClient = async (secret, server, port, opts) => {
499
520
  if (!codeChallenge) throw new Error("failed to derive a PKCE code challenge");
500
521
  const state = (0, node_crypto.randomBytes)(STATE_BYTES).toString("hex");
501
522
  opts.onAuthUrl?.(buildConsentUrl(client, codeChallenge, state));
502
- const code = await waitForAuthCode(server, state, opts.timeoutMs ?? AUTH_TIMEOUT_MS);
523
+ const code = await waitForAuthCode(server, state, opts.timeoutMs ?? AUTH_TIMEOUT_MS, opts.signal);
503
524
  const { tokens } = await client.getToken({
504
525
  code,
505
526
  codeVerifier
@@ -512,11 +533,18 @@ var authorizeWithBroker = async (server, port, opts) => {
512
533
  const { authUrl, state } = await brokerStart(port, codeChallenge);
513
534
  opts.onAuthUrl?.(authUrl);
514
535
  return await brokerExchange({
515
- code: await waitForAuthCode(server, state, opts.timeoutMs ?? AUTH_TIMEOUT_MS),
536
+ code: await waitForAuthCode(server, state, opts.timeoutMs ?? AUTH_TIMEOUT_MS, opts.signal),
516
537
  state,
517
538
  codeVerifier
518
539
  });
519
540
  };
541
+ var commitLinkedTokens = async (tokens, issuedVia, opts) => {
542
+ if (opts.signal?.aborted) throw new Error(GOOGLE_AUTH_CANCELLED);
543
+ return await saveGoogleTokens({
544
+ ...tokens,
545
+ issuedVia
546
+ }, opts.home);
547
+ };
520
548
  async function authorizeGoogle(opts = {}) {
521
549
  const presence = await clientSecretPresence(opts.home);
522
550
  if (presence === "ambiguous") await loadClientSecret(opts.home);
@@ -524,10 +552,7 @@ async function authorizeGoogle(opts = {}) {
524
552
  const { server, port } = await startLoopbackServer();
525
553
  try {
526
554
  const issuedVia = useLocalClient ? "local" : "broker";
527
- return await saveGoogleTokens({
528
- ...useLocalClient ? await authorizeWithLocalClient(await loadClientSecret(opts.home), server, port, opts) : await authorizeWithBroker(server, port, opts),
529
- issuedVia
530
- }, opts.home);
555
+ return await commitLinkedTokens(useLocalClient ? await authorizeWithLocalClient(await loadClientSecret(opts.home), server, port, opts) : await authorizeWithBroker(server, port, opts), issuedVia, opts);
531
556
  } finally {
532
557
  server.close();
533
558
  }
@@ -535,25 +560,38 @@ async function authorizeGoogle(opts = {}) {
535
560
  //#endregion
536
561
  //#region src/google/authFlow.ts
537
562
  var createGoogleAuthFlow = (authorize) => {
538
- let inFlightStart = null;
539
563
  let flowRunning = false;
540
564
  let lastError = null;
541
- const launchFlow = () => new Promise((resolve, reject) => {
565
+ let active = null;
566
+ const launch = () => {
567
+ const controller = new AbortController();
568
+ active = controller;
542
569
  flowRunning = true;
543
- authorize({ onAuthUrl: (url) => resolve({ authUrl: url }) }).then(() => log.info("google", "authorize flow completed")).catch((err) => {
544
- lastError = errorMessage(err);
545
- log.warn("google", "authorize flow failed", { error: lastError });
546
- reject(err instanceof Error ? err : new Error(String(err)));
547
- }).finally(() => {
548
- flowRunning = false;
549
- inFlightStart = null;
570
+ return new Promise((resolve, reject) => {
571
+ authorize({
572
+ onAuthUrl: (url) => resolve({ authUrl: url }),
573
+ signal: controller.signal
574
+ }).then(() => log.info("google", "authorize flow completed")).catch((err) => {
575
+ if (!controller.signal.aborted) {
576
+ lastError = errorMessage(err);
577
+ log.warn("google", "authorize flow failed", { error: lastError });
578
+ }
579
+ reject(err instanceof Error ? err : new Error(String(err)));
580
+ }).finally(() => {
581
+ if (active === controller) {
582
+ flowRunning = false;
583
+ active = null;
584
+ }
585
+ });
550
586
  });
551
- });
587
+ };
588
+ const cancel = () => {
589
+ active?.abort();
590
+ };
552
591
  const start = () => {
553
- if (inFlightStart) return inFlightStart;
592
+ cancel();
554
593
  lastError = null;
555
- inFlightStart = launchFlow();
556
- return inFlightStart;
594
+ return launch();
557
595
  };
558
596
  const status = () => ({
559
597
  pending: flowRunning,
@@ -561,6 +599,7 @@ var createGoogleAuthFlow = (authorize) => {
561
599
  });
562
600
  return {
563
601
  start,
602
+ cancel,
564
603
  status
565
604
  };
566
605
  };
@@ -863,6 +902,7 @@ async function deleteDriveFile(accessToken, input) {
863
902
  }
864
903
  //#endregion
865
904
  exports.DEFAULT_LIST_MAX_RESULTS = DEFAULT_LIST_MAX_RESULTS;
905
+ exports.GOOGLE_AUTH_CANCELLED = GOOGLE_AUTH_CANCELLED;
866
906
  exports.GOOGLE_CALENDARLIST_SCOPE = GOOGLE_CALENDARLIST_SCOPE;
867
907
  exports.GOOGLE_CALENDAR_SCOPE = GOOGLE_CALENDAR_SCOPE;
868
908
  exports.GOOGLE_DRIVE_FILE_SCOPE = GOOGLE_DRIVE_FILE_SCOPE;
@@ -879,6 +919,7 @@ exports.buildMultipartBody = buildMultipartBody;
879
919
  exports.calendarApiError = calendarApiError;
880
920
  exports.clientSecretPresence = clientSecretPresence;
881
921
  exports.collectCalendarPages = collectCalendarPages;
922
+ exports.commitLinkedTokens = commitLinkedTokens;
882
923
  exports.completeTask = completeTask;
883
924
  exports.configureGoogleHost = configureGoogleHost;
884
925
  exports.createCalendarEvent = createCalendarEvent;