@phosphorco/bb-cross-references 0.1.1 → 0.3.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.
package/dist/react.js CHANGED
@@ -365,7 +365,279 @@ function referenceLabelError(value) {
365
365
  }
366
366
 
367
367
  // src/index.ts
368
+ import { z as z3 } from "zod";
369
+
370
+ // src/recognition.ts
368
371
  import { z } from "zod";
372
+ import { canonicalJson, SourceIdentitySchema, SafeHrefSchema } from "@phosphorco/bb-context-recognition";
373
+ var RECOGNITION_CODEC_VERSION = 1;
374
+ var MAX_RECOGNITION_IDENTITY_BYTES = 16384;
375
+ function recognitionIdentity(source, verified) {
376
+ const parsed = SourceIdentitySchema.parse(source);
377
+ if (parsed.provider === "bb.thread") {
378
+ if (!verified || verified.id !== parsed.id || verified.deletedAt != null)
379
+ throw new Error("A verified existing thread is required.");
380
+ return threadIdentity(verified.projectId, verified.id);
381
+ }
382
+ if (parsed.provider === "bb.file")
383
+ throw new Error("Use verifiedFileIdentity with verified frame metadata.");
384
+ if (parsed.provider === "bb.url") {
385
+ const href = SafeHrefSchema.parse(parsed.id);
386
+ return { provider: "url", keys: canonicalizeIdentity({ provider: "url", keys: { href: new URL(href).href } }).keys };
387
+ }
388
+ return { provider: "recognition", keys: { provider: parsed.provider, identity: sha256Hex(canonicalJson([parsed.provider, parsed.id])) } };
389
+ }
390
+ function recognitionIdentityRecord(source) {
391
+ const parsed = SourceIdentitySchema.parse(source);
392
+ const json = canonicalJson({ provider: parsed.provider, id: parsed.id });
393
+ if (new TextEncoder().encode(json).length > MAX_RECOGNITION_IDENTITY_BYTES)
394
+ throw new Error("Recognition identity mapping exceeds its bound.");
395
+ return json;
396
+ }
397
+ var VerifiedFileTargetSchema = z.discriminatedUnion("kind", [
398
+ z.strictObject({ kind: z.literal("workspace"), environmentId: fileOwnerId(), path: verifiedFilePath() }),
399
+ z.strictObject({ kind: z.literal("thread-storage"), threadId: fileOwnerId(), path: verifiedFilePath() })
400
+ ]);
401
+ function fileOwnerId() {
402
+ return z.string().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/);
403
+ }
404
+ function verifiedFilePath() {
405
+ return z.string().min(1).max(4096).refine((path) => !path.startsWith("/") && !/[\\:%?#\u0000-\u001f\u007f]/u.test(path) && path.split("/").every((part) => part.length > 0 && part !== "." && part !== ".."), "Expected a canonical relative file path.");
406
+ }
407
+ function verifiedFileIdentity(value) {
408
+ const file = VerifiedFileTargetSchema.parse(value);
409
+ const owner = file.kind === "workspace" ? file.environmentId : file.threadId;
410
+ return { provider: "recognition", keys: { provider: "bb.file", identity: sha256Hex(canonicalJson(["bb.file", file.kind, owner, file.path])) } };
411
+ }
412
+ function verifiedFileIdentityRecord(value) {
413
+ const json = canonicalJson({ provider: "bb.file", verifiedFile: VerifiedFileTargetSchema.parse(value) });
414
+ if (new TextEncoder().encode(json).length > MAX_RECOGNITION_IDENTITY_BYTES)
415
+ throw new Error("Verified file mapping exceeds its bound.");
416
+ return json;
417
+ }
418
+ // src/evidence-v2.ts
419
+ import { z as z2 } from "zod";
420
+ import { ContextBundleV1Schema, SafeHrefSchema as SafeHrefSchema2, CandidateV1Schema, SourceIdentitySchema as SourceIdentitySchema2 } from "@phosphorco/bb-context-recognition";
421
+ var MENTION_V2_LIMITS = Object.freeze({
422
+ responseBytes: 1048576,
423
+ inputBytes: 65536,
424
+ pageSize: 100,
425
+ cursorBytes: 4096,
426
+ excerptCodePoints: 320,
427
+ excerptBytes: 1280,
428
+ rowBytes: 131072,
429
+ readMs: 2000,
430
+ callMs: 5000,
431
+ lookupMs: 1500,
432
+ lookupCalls: 8
433
+ });
434
+ var MENTION_V2_METHODS = Object.freeze({ list: "crossReferencesV2ListMentions", resolve: "crossReferencesV2ResolveLookup" });
435
+ var integer = () => z2.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
436
+ var time = () => integer().max(8640000000000000);
437
+ var digest = z2.string().regex(/^[a-f0-9]{64}$/);
438
+ var text = (n) => z2.string().max(n).refine((v) => utf8ByteLength(v) <= n, "UTF8 byte bound exceeded.");
439
+ var id = z2.string().min(1).max(256).refine((v) => !/[\p{Cc}]/u.test(v));
440
+ var producer = z2.string().regex(/^[a-z][a-z0-9._-]{0,63}$/);
441
+ var keys = z2.record(z2.string(), z2.string()).refine((v) => Object.keys(v).length <= 16);
442
+ function isUtf16CodePointBoundary(text2, offset) {
443
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset > text2.length)
444
+ return false;
445
+ const before = text2.charCodeAt(offset - 1), after = text2.charCodeAt(offset);
446
+ return !(before >= 55296 && before <= 56319 && after >= 56320 && after <= 57343);
447
+ }
448
+ function wellFormedUtf16(text2) {
449
+ for (const point of text2) {
450
+ const value = point.codePointAt(0);
451
+ if (value >= 55296 && value <= 57343)
452
+ return false;
453
+ }
454
+ return true;
455
+ }
456
+ var identityShape = { provider: z2.string().min(1).max(64), keys };
457
+ var identityInputV2Schema = z2.strictObject(identityShape).superRefine((v, c) => {
458
+ try {
459
+ canonicalizeIdentity(v);
460
+ } catch {
461
+ c.addIssue({ code: "custom", message: "Invalid resource identity." });
462
+ }
463
+ });
464
+ var presentation = z2.object({ label: text(256).min(1), url: text(2048).optional(), detail: text(1024).optional() }).passthrough();
465
+ var resourceOutputV2Schema = z2.object({ ...identityShape, presentation }).passthrough().superRefine((v, c) => {
466
+ try {
467
+ canonicalizeResource({ provider: v.provider, keys: v.keys, presentation: { label: v.presentation.label, ...v.presentation.url === undefined ? {} : { url: v.presentation.url }, ...v.presentation.detail === undefined ? {} : { detail: v.presentation.detail } } });
468
+ } catch {
469
+ c.addIssue({ code: "custom", message: "Invalid resource." });
470
+ }
471
+ });
472
+ var safeAuthoredHrefSchema = SafeHrefSchema2.refine((v) => utf8ByteLength(v) <= 16384 && !hasSensitiveUrlParameter(new URL(v, "https://local.invalid")), "Unsafe destination.");
473
+ var mentionQueryV2Schema = z2.discriminatedUnion("kind", [
474
+ z2.strictObject({ kind: z2.literal("resource"), target: identityInputV2Schema, relation: z2.enum(["self", "github-pr-family"]) }).refine((v) => v.relation === "self" || v.target.provider === "recognition" && v.target.keys.provider === "github" && /^[a-f0-9]{64}$/.test(v.target.keys.identity ?? ""), "Expected a GitHub root identity."),
475
+ z2.strictObject({ kind: z2.literal("authored-url"), href: safeAuthoredHrefSchema })
476
+ ]);
477
+ var listMentionsInputV2Schema = z2.strictObject({
478
+ version: z2.literal(2),
479
+ query: mentionQueryV2Schema,
480
+ source: identityInputV2Schema.optional(),
481
+ producerPluginId: producer.optional(),
482
+ pageSize: z2.number().int().min(1).max(100).optional(),
483
+ cursor: text(4096).optional(),
484
+ ifSnapshot: digest.optional()
485
+ }).refine((v) => !(v.cursor !== undefined && v.ifSnapshot !== undefined), "Cursor and conditional are exclusive.");
486
+ var spanShape = { start: integer(), end: integer() };
487
+ var spanOutputV2Schema = z2.object(spanShape).passthrough().refine((v) => v.end > v.start);
488
+ var readyShape = {
489
+ state: z2.literal("ready"),
490
+ text: z2.string().refine(wellFormedUtf16, "Excerpt text must be well-formed UTF16.").refine((v) => [...v].length <= 320 && utf8ByteLength(v) <= 1280),
491
+ sourceSpan: spanOutputV2Schema,
492
+ matchSpan: spanOutputV2Schema,
493
+ clippedBefore: z2.boolean(),
494
+ clippedAfter: z2.boolean(),
495
+ matchClippedBefore: z2.boolean(),
496
+ matchClippedAfter: z2.boolean(),
497
+ codecVersion: z2.literal(1)
498
+ };
499
+ var readyCoordinates = (v) => v.matchSpan.end <= v.text.length && v.sourceSpan.end - v.sourceSpan.start === v.text.length && isUtf16CodePointBoundary(v.text, v.matchSpan.start) && isUtf16CodePointBoundary(v.text, v.matchSpan.end);
500
+ var excerptV2Schema = z2.discriminatedUnion("state", [
501
+ z2.object(readyShape).passthrough().refine(readyCoordinates, "Excerpt bounds must be code-point aligned."),
502
+ z2.object({ state: z2.literal("unavailable"), reason: z2.enum(["not-materialized", "indivisible-word", "no-eligible-context"]), codecVersion: z2.literal(1) }).passthrough()
503
+ ]);
504
+ var excerptRecordV2Schema = z2.discriminatedUnion("state", [
505
+ z2.strictObject({ ...readyShape, sourceSpan: z2.strictObject(spanShape).refine((v) => v.end > v.start), matchSpan: z2.strictObject(spanShape).refine((v) => v.end > v.start) }).refine(readyCoordinates, "Excerpt bounds must be code-point aligned."),
506
+ z2.strictObject({ state: z2.literal("unavailable"), reason: z2.enum(["indivisible-word", "no-eligible-context"]), codecVersion: z2.literal(1) })
507
+ ]);
508
+ var locatorOutputV2Schema = z2.object({ kind: z2.literal("conversation"), threadId: id, messageId: id, messageSeq: integer(), anchorSeq: integer().nullable(), role: z2.enum(["user", "assistant"]) }).passthrough();
509
+ var recognitionProvenance = z2.object({
510
+ pluginId: id,
511
+ origin: z2.enum(["builtin", "contributed"]),
512
+ confidence: CandidateV1Schema.shape.confidence,
513
+ recognition: z2.object({
514
+ basis: z2.enum(["explicit", "text-url", "existing-link", "git-remote", "context"]),
515
+ explanation: z2.string().min(1).max(200),
516
+ evidence: z2.object({ span: spanOutputV2Schema.optional(), link: integer().optional(), remote: id.optional() }).passthrough().optional()
517
+ }).passthrough(),
518
+ source: SourceIdentitySchema2.passthrough(),
519
+ authoredHref: safeAuthoredHrefSchema.optional(),
520
+ verifiedFile: VerifiedFileTargetSchema.optional()
521
+ }).passthrough();
522
+ var verifiedFileOutput = z2.union([
523
+ z2.object({ kind: z2.literal("workspace"), environmentId: id, path: z2.string().min(1).max(4096) }).passthrough(),
524
+ z2.object({ kind: z2.literal("thread-storage"), threadId: id, path: z2.string().min(1).max(4096) }).passthrough()
525
+ ]);
526
+ var provenanceOutput = recognitionProvenance.extend({ verifiedFile: verifiedFileOutput.optional() });
527
+ var claimShape = {
528
+ source: resourceOutputV2Schema,
529
+ target: resourceOutputV2Schema,
530
+ producerPluginId: producer,
531
+ graphRevision: integer(),
532
+ cap: z2.object({ state: z2.enum(["uncapped", "capped", "unknown"]), limit: z2.literal(100).nullable(), sourceHistoryUnknown: z2.boolean().nullable() }).passthrough()
533
+ };
534
+ var knownItem = z2.discriminatedUnion("kind", [
535
+ z2.object({
536
+ ...claimShape,
537
+ kind: z2.literal("occurrence"),
538
+ evidenceRevision: integer().min(1),
539
+ occurrenceKey: digest,
540
+ locator: locatorOutputV2Schema,
541
+ sourceContentRevision: digest,
542
+ span: spanOutputV2Schema,
543
+ excerpt: excerptV2Schema,
544
+ messageCreatedAt: time(),
545
+ observedAt: time(),
546
+ confirmation: z2.enum(["observed", "retained-unconfirmed"]),
547
+ provenance: provenanceOutput,
548
+ authoredUrlState: z2.enum(["exact", "not-url", "unknown"])
549
+ }).passthrough(),
550
+ z2.object({ ...claimShape, kind: z2.literal("claim-without-evidence"), reason: z2.enum(["legacy", "producer-no-evidence", "not-yet-collected"]), matchBasis: z2.enum(["primary-resource", "primary-url-identity"]) }).passthrough(),
551
+ z2.object({ ...claimShape, kind: z2.literal("unsupported"), reason: z2.literal("unsupported-format") }).passthrough()
552
+ ]);
553
+ var mentionItemV2Schema = z2.unknown().transform((raw, ctx) => {
554
+ const r = raw;
555
+ const unknown = (value, known) => typeof value === "string" && !known.includes(value);
556
+ const future = !!r && typeof r === "object" && (unknown(r.kind, ["occurrence", "claim-without-evidence", "unsupported"]) || r.kind === "occurrence" && (unknown(r.locator?.kind, ["conversation"]) || unknown(r.excerpt?.state, ["ready", "unavailable"]) || typeof r.excerpt?.codecVersion === "number" && r.excerpt.codecVersion !== 1 || unknown(r.confirmation, ["observed", "retained-unconfirmed"]) || unknown(r.authoredUrlState, ["exact", "not-url", "unknown"]) || unknown(r.locator?.role, ["user", "assistant"]) || unknown(r.provenance?.origin, ["builtin", "contributed"]) || unknown(r.provenance?.confidence, ["high", "medium", "low"]) || unknown(r.provenance?.recognition?.basis, ["explicit", "text-url", "existing-link", "git-remote", "context"]) || r.excerpt?.state === "unavailable" && unknown(r.excerpt.reason, ["not-materialized", "indivisible-word", "no-eligible-context"])) || r.kind === "claim-without-evidence" && (unknown(r.reason, ["legacy", "producer-no-evidence", "not-yet-collected"]) || unknown(r.matchBasis, ["primary-resource", "primary-url-identity"])) || unknown(r.cap?.state, ["uncapped", "capped", "unknown"]));
557
+ if (future && (!r.cap || !z2.object({ state: z2.string(), limit: z2.literal(100).nullable(), sourceHistoryUnknown: z2.boolean().nullable() }).safeParse(r.cap).success)) {
558
+ ctx.addIssue({ code: "custom", message: "Invalid required claim cap." });
559
+ return z2.NEVER;
560
+ }
561
+ const candidate = future ? {
562
+ source: r.source,
563
+ target: r.target,
564
+ producerPluginId: r.producerPluginId,
565
+ graphRevision: r.graphRevision,
566
+ cap: { state: "unknown", limit: null, sourceHistoryUnknown: null },
567
+ kind: "unsupported",
568
+ reason: "unsupported-format"
569
+ } : raw;
570
+ const parsed = knownItem.safeParse(candidate);
571
+ if (parsed.success)
572
+ return parsed.data;
573
+ ctx.addIssue({ code: "custom", message: "Invalid mention item." });
574
+ return z2.NEVER;
575
+ });
576
+ var mentionCountsV2Schema = z2.object({ retainedOccurrences: integer(), confirmedOccurrences: integer(), unconfirmedOccurrences: integer(), producerClaims: integer(), indexedSources: integer(), claimsWithoutLocations: integer(), excerptUnavailable: integer() }).passthrough().refine((v) => v.confirmedOccurrences + v.unconfirmedOccurrences === v.retainedOccurrences && v.claimsWithoutLocations <= v.producerClaims && v.indexedSources <= v.producerClaims && v.excerptUnavailable <= v.retainedOccurrences);
577
+ var coverageV2Schema = z2.object({
578
+ scope: z2.literal("known-sources"),
579
+ collectionIncomplete: z2.boolean(),
580
+ retentionLimited: z2.boolean(),
581
+ capHistoryUnknown: z2.boolean(),
582
+ legacyClaimsPresent: z2.boolean(),
583
+ evidenceStateUnknown: z2.boolean(),
584
+ authoredUrlCoverage: z2.object({ state: z2.enum(["complete-for-known-locations", "partial"]), unknownLocations: integer(), scope: z2.literal("known-locations"), watermark: digest }).passthrough(),
585
+ reasons: z2.array(text(128)).max(32),
586
+ reasonsClipped: z2.boolean(),
587
+ checkedAt: time().nullable()
588
+ }).passthrough();
589
+ var listMentionsOutputV2Schema = z2.discriminatedUnion("status", [
590
+ z2.object({ version: z2.literal(2), status: z2.literal("page"), snapshot: digest, items: z2.array(mentionItemV2Schema).max(100), counts: mentionCountsV2Schema, coverage: coverageV2Schema, nextCursor: text(4096).nullable() }).passthrough(),
591
+ z2.object({ version: z2.literal(2), status: z2.literal("not-modified"), snapshot: digest, coverage: coverageV2Schema }).passthrough(),
592
+ z2.object({ version: z2.literal(2), status: z2.literal("restart"), reason: z2.literal("snapshot-changed"), snapshot: digest }).passthrough(),
593
+ z2.object({ version: z2.literal(2), status: z2.literal("unavailable"), reason: z2.enum(["index-warming", "read-budget"]), retryable: z2.boolean() }).passthrough()
594
+ ]);
595
+ var lookupContextV2Schema = ContextBundleV1Schema.omit({ consumer: true, links: true }).extend({ links: z2.array(z2.strictObject({ href: safeAuthoredHrefSchema })).max(16).optional() });
596
+ var resolveLookupInputV2Schema = z2.strictObject({ version: z2.literal(2), text: z2.string().min(1).max(4096).refine((v) => utf8ByteLength(v) <= 16384), mode: z2.enum(["recognize", "exact-url"]), context: lookupContextV2Schema.optional() });
597
+ var identityOutput = z2.object(identityShape).passthrough().superRefine((v, c) => {
598
+ try {
599
+ canonicalizeIdentity({ provider: v.provider, keys: v.keys });
600
+ } catch {
601
+ c.addIssue({ code: "custom", message: "Invalid lookup identity." });
602
+ }
603
+ });
604
+ var queryOutput = z2.discriminatedUnion("kind", [
605
+ z2.object({ kind: z2.literal("resource"), target: identityOutput, relation: z2.enum(["self", "github-pr-family"]) }).passthrough(),
606
+ z2.object({ kind: z2.literal("authored-url"), href: safeAuthoredHrefSchema }).passthrough()
607
+ ]);
608
+ var resolveLookupOutputV2Schema = z2.object({
609
+ version: z2.literal(2),
610
+ state: z2.enum(["ready", "ambiguous", "unrecognized", "incomplete"]),
611
+ options: z2.array(z2.object({ query: queryOutput, label: text(256), inputSpan: spanOutputV2Schema, basis: z2.enum(["supplier", "native", "stored-codec"]), reasons: z2.array(text(128)).max(16) }).passthrough()).max(8),
612
+ reasons: z2.array(text(128)).max(16)
613
+ }).passthrough();
614
+ var crossReferencesV2RpcSchemas = {
615
+ crossReferencesV2ListMentions: { input: listMentionsInputV2Schema, output: listMentionsOutputV2Schema },
616
+ crossReferencesV2ResolveLookup: { input: resolveLookupInputV2Schema, output: resolveLookupOutputV2Schema }
617
+ };
618
+ var mentionsChangedV2Schema = z2.object({ version: z2.literal(2), producerPluginId: producer, sourceIdentityDigest: digest, graphRevision: integer(), evidenceRevision: integer().nullable(), affectedIdentityDigests: z2.array(digest).max(512), scopeListClipped: z2.boolean() }).passthrough();
619
+ var MENTIONS_V2_CHANNEL = "cross-references-mentions-v2-changed";
620
+ // src/lookup.ts
621
+ function githubLookup(value) {
622
+ if (!safeAuthoredHrefSchema.safeParse(value).success)
623
+ return null;
624
+ let u;
625
+ try {
626
+ u = new URL(value);
627
+ } catch {
628
+ return null;
629
+ }
630
+ if (u.hostname.toLowerCase() !== "github.com" || u.port || u.username || u.password)
631
+ return null;
632
+ const p = u.pathname.replace(/\/$/, "").split("/").slice(1);
633
+ if (!/^[a-z0-9](?:[a-z0-9-]{0,37}[a-z0-9])?$/i.test(p[0] ?? "") || !/^[a-z0-9_.-]{1,100}$/i.test(p[1] ?? "") || [".", ".."].includes(p[1] ?? "") || !["pull", "issues"].includes(p[2] ?? "") || !/^[1-9]\d*$/.test(p[3] ?? "") || !Number.isSafeInteger(Number(p[3])))
634
+ return null;
635
+ const repo = `${p[0]}/${p[1]}`.toLowerCase(), n = String(Number(p[3])), kind = p[2] === "pull" ? "pull-request" : "issue";
636
+ const source = { provider: "github", id: `github.com/${repo}#${n}`, kind };
637
+ return { source, query: { kind: "resource", target: recognitionIdentity(source), relation: kind === "pull-request" ? "github-pr-family" : "self" }, label: `${repo}#${n}` };
638
+ }
639
+
640
+ // src/index.ts
369
641
  var FORWARD_REFERENCE_CHECK_LIMIT = 10;
370
642
  function assertInputRecord(value) {
371
643
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
@@ -439,10 +711,10 @@ var namePattern = /^[a-z][a-z0-9._-]{0,63}$/;
439
711
  var uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
440
712
  var digestPattern = /^[0-9a-f]{64}$/;
441
713
  var safeInteger = (schema) => schema.refine(Number.isSafeInteger, { message: "must be a safe integer" });
442
- var presentationSchema = z.object({
443
- label: z.string().max(MAX_PRESENTATION_LABEL_BYTES),
444
- detail: z.string().max(MAX_PRESENTATION_DETAIL_BYTES).optional(),
445
- url: z.string().max(MAX_PRESENTATION_URL_BYTES).optional()
714
+ var presentationSchema = z3.object({
715
+ label: z3.string().max(MAX_PRESENTATION_LABEL_BYTES),
716
+ detail: z3.string().max(MAX_PRESENTATION_DETAIL_BYTES).optional(),
717
+ url: z3.string().max(MAX_PRESENTATION_URL_BYTES).optional()
446
718
  }).strict().superRefine((value, context) => {
447
719
  try {
448
720
  canonicalizeResource({ provider: "test", keys: { resource: "placeholder" }, presentation: value });
@@ -450,9 +722,9 @@ var presentationSchema = z.object({
450
722
  context.addIssue({ code: "custom", message: cause instanceof Error ? cause.message : String(cause) });
451
723
  }
452
724
  });
453
- var resourceSchema = z.object({
454
- provider: z.string().max(64).regex(namePattern),
455
- keys: z.record(z.string().max(64), z.string().max(MAX_KEY_VALUE_BYTES)),
725
+ var resourceSchema = z3.object({
726
+ provider: z3.string().max(64).regex(namePattern),
727
+ keys: z3.record(z3.string().max(64), z3.string().max(MAX_KEY_VALUE_BYTES)),
456
728
  presentation: presentationSchema
457
729
  }).strict().superRefine((value, context) => {
458
730
  try {
@@ -461,9 +733,9 @@ var resourceSchema = z.object({
461
733
  context.addIssue({ code: "custom", message: cause instanceof Error ? cause.message : String(cause) });
462
734
  }
463
735
  });
464
- var resourceIdentitySchema = z.object({
465
- provider: z.string().max(64).regex(namePattern),
466
- keys: z.record(z.string().max(64), z.string().max(MAX_KEY_VALUE_BYTES))
736
+ var resourceIdentitySchema = z3.object({
737
+ provider: z3.string().max(64).regex(namePattern),
738
+ keys: z3.record(z3.string().max(64), z3.string().max(MAX_KEY_VALUE_BYTES))
467
739
  }).strict().superRefine((value, context) => {
468
740
  try {
469
741
  canonicalizeIdentity(value);
@@ -471,19 +743,19 @@ var resourceIdentitySchema = z.object({
471
743
  context.addIssue({ code: "custom", message: cause instanceof Error ? cause.message : String(cause) });
472
744
  }
473
745
  });
474
- var producerPluginIdSchema = z.string().max(64).regex(namePattern);
475
- var mutationIdSchema = z.string().max(MAX_MUTATION_ID_BYTES).regex(uuidPattern);
476
- var revisionSchema = safeInteger(z.number().int());
477
- var applyProjectionInputSchema = z.object({
478
- protocolVersion: z.literal(PROTOCOL_VERSION),
746
+ var producerPluginIdSchema = z3.string().max(64).regex(namePattern);
747
+ var mutationIdSchema = z3.string().max(MAX_MUTATION_ID_BYTES).regex(uuidPattern);
748
+ var revisionSchema = safeInteger(z3.number().int());
749
+ var applyProjectionInputSchema = z3.object({
750
+ protocolVersion: z3.literal(PROTOCOL_VERSION),
479
751
  producerPluginId: producerPluginIdSchema,
480
752
  mutationId: mutationIdSchema,
481
753
  source: resourceSchema,
482
754
  revision: revisionSchema.positive(),
483
755
  expectedRevision: revisionSchema.nonnegative(),
484
- payloadDigest: z.string().regex(digestPattern),
485
- tombstone: z.boolean(),
486
- targets: z.array(resourceSchema).max(MAX_TARGETS)
756
+ payloadDigest: z3.string().regex(digestPattern),
757
+ tombstone: z3.boolean(),
758
+ targets: z3.array(resourceSchema).max(MAX_TARGETS)
487
759
  }).strict().superRefine((value, context) => {
488
760
  try {
489
761
  normalizeProjectionCommand(value);
@@ -491,78 +763,78 @@ var applyProjectionInputSchema = z.object({
491
763
  context.addIssue({ code: "custom", message: cause instanceof Error ? cause.message : String(cause) });
492
764
  }
493
765
  });
494
- var applyProjectionResponseSchema = z.object({
495
- outcome: z.enum(["applied", "duplicate", "equal", "stale", "conflict", "cas-mismatch"]),
766
+ var applyProjectionResponseSchema = z3.object({
767
+ outcome: z3.enum(["applied", "duplicate", "equal", "stale", "conflict", "cas-mismatch"]),
496
768
  currentRevision: revisionSchema.nonnegative(),
497
- currentDigest: z.string().regex(digestPattern).nullable()
769
+ currentDigest: z3.string().regex(digestPattern).nullable()
498
770
  }).strict();
499
- var projectionSchema = z.object({
771
+ var projectionSchema = z3.object({
500
772
  producerPluginId: producerPluginIdSchema,
501
773
  source: resourceSchema,
502
774
  revision: revisionSchema.nonnegative(),
503
775
  mutationId: mutationIdSchema,
504
- payloadDigest: z.string().regex(digestPattern),
505
- tombstone: z.boolean(),
506
- targets: z.array(resourceSchema).max(MAX_TARGETS)
776
+ payloadDigest: z3.string().regex(digestPattern),
777
+ tombstone: z3.boolean(),
778
+ targets: z3.array(resourceSchema).max(MAX_TARGETS)
507
779
  }).strict();
508
- var getProjectionInputSchema = z.object({
780
+ var getProjectionInputSchema = z3.object({
509
781
  producerPluginId: producerPluginIdSchema,
510
782
  source: resourceIdentitySchema
511
783
  }).strict();
512
- var getProjectionOutputSchema = z.object({ projection: projectionSchema.nullable() }).strict();
513
- var backlinkRowSchema = z.object({
784
+ var getProjectionOutputSchema = z3.object({ projection: projectionSchema.nullable() }).strict();
785
+ var backlinkRowSchema = z3.object({
514
786
  source: resourceSchema,
515
787
  producerPluginId: producerPluginIdSchema,
516
788
  revision: revisionSchema.nonnegative(),
517
789
  targetPresentation: presentationSchema,
518
- position: z.number().int().min(0).max(MAX_TARGETS - 1).refine(Number.isSafeInteger),
790
+ position: z3.number().int().min(0).max(MAX_TARGETS - 1).refine(Number.isSafeInteger),
519
791
  lastSeenAt: revisionSchema.nonnegative().nullable().optional()
520
792
  }).strict();
521
- var listBacklinksInputSchema = z.object({
793
+ var listBacklinksInputSchema = z3.object({
522
794
  target: resourceIdentitySchema,
523
- pageSize: z.number().int().min(1).max(100).refine(Number.isSafeInteger).optional(),
524
- cursor: z.string().max(4096).optional()
795
+ pageSize: z3.number().int().min(1).max(100).refine(Number.isSafeInteger).optional(),
796
+ cursor: z3.string().max(4096).optional()
525
797
  }).strict();
526
- var listBacklinksOutputSchema = z.object({
527
- rows: z.array(backlinkRowSchema).max(100),
798
+ var listBacklinksOutputSchema = z3.object({
799
+ rows: z3.array(backlinkRowSchema).max(100),
528
800
  total: revisionSchema.nonnegative(),
529
- nextCursor: z.string().max(4096).nullable()
801
+ nextCursor: z3.string().max(4096).nullable()
530
802
  }).strict();
531
- var forwardReferenceRowSchema = z.object({
803
+ var forwardReferenceRowSchema = z3.object({
532
804
  target: resourceSchema,
533
805
  producerPluginId: producerPluginIdSchema,
534
806
  revision: revisionSchema.nonnegative(),
535
- position: z.number().int().min(0).max(MAX_TARGETS - 1).refine(Number.isSafeInteger),
807
+ position: z3.number().int().min(0).max(MAX_TARGETS - 1).refine(Number.isSafeInteger),
536
808
  lastSeenAt: revisionSchema.nonnegative().nullable().optional()
537
809
  }).strict();
538
- var listForwardReferencesInputSchema = z.object({
810
+ var listForwardReferencesInputSchema = z3.object({
539
811
  source: resourceIdentitySchema,
540
812
  producerPluginId: producerPluginIdSchema.optional(),
541
- pageSize: z.number().int().min(1).max(100).refine(Number.isSafeInteger).optional(),
542
- cursor: z.string().max(4096).optional()
813
+ pageSize: z3.number().int().min(1).max(100).refine(Number.isSafeInteger).optional(),
814
+ cursor: z3.string().max(4096).optional()
543
815
  }).strict();
544
- var listForwardReferencesOutputSchema = z.object({
545
- rows: z.array(forwardReferenceRowSchema).max(100),
816
+ var listForwardReferencesOutputSchema = z3.object({
817
+ rows: z3.array(forwardReferenceRowSchema).max(100),
546
818
  total: revisionSchema.nonnegative(),
547
- nextCursor: z.string().max(4096).nullable()
819
+ nextCursor: z3.string().max(4096).nullable()
548
820
  }).strict();
549
- var checkForwardReferencesInputSchema = z.object({
821
+ var checkForwardReferencesInputSchema = z3.object({
550
822
  source: resourceIdentitySchema,
551
823
  producerPluginId: producerPluginIdSchema.optional()
552
824
  }).strict();
553
- var forwardReferenceStatusSchema = z.object({
554
- url: z.string().max(MAX_PRESENTATION_URL_BYTES),
555
- status: z.number().int().min(100).max(599).nullable(),
556
- label: z.string().min(1).max(128)
825
+ var forwardReferenceStatusSchema = z3.object({
826
+ url: z3.string().max(MAX_PRESENTATION_URL_BYTES),
827
+ status: z3.number().int().min(100).max(599).nullable(),
828
+ label: z3.string().min(1).max(128)
557
829
  }).strict();
558
- var checkForwardReferencesOutputSchema = z.array(forwardReferenceStatusSchema).max(FORWARD_REFERENCE_CHECK_LIMIT);
830
+ var checkForwardReferencesOutputSchema = z3.array(forwardReferenceStatusSchema).max(FORWARD_REFERENCE_CHECK_LIMIT);
559
831
  var CROSS_REFERENCES_PLUGIN_ID = "cross-references";
560
832
  var CROSS_REFERENCES_PROTOCOL = "cross-references";
561
833
  var LIMITS = Object.freeze({ callMs: 5000, describeMs: 1000, responseBytes: 1024 * 1024 });
562
- var describeInputSchema = z.null();
563
- var describeOutputSchema = z.object({
564
- protocol: z.literal(CROSS_REFERENCES_PROTOCOL),
565
- versions: z.array(z.number().int().positive().refine(Number.isSafeInteger)).max(16)
834
+ var describeInputSchema = z3.null();
835
+ var describeOutputSchema = z3.object({
836
+ protocol: z3.literal(CROSS_REFERENCES_PROTOCOL),
837
+ versions: z3.array(z3.number().int().positive().refine(Number.isSafeInteger)).max(16)
566
838
  });
567
839
  var crossReferencesRpcSchemas = {
568
840
  "crossReferences.describe": { input: describeInputSchema, output: describeOutputSchema },
@@ -572,10 +844,10 @@ var crossReferencesRpcSchemas = {
572
844
  listForwardReferences: { input: listForwardReferencesInputSchema, output: listForwardReferencesOutputSchema },
573
845
  checkForwardReferences: { input: checkForwardReferencesInputSchema, output: checkForwardReferencesOutputSchema }
574
846
  };
575
- var referenceSnapshotSchema = z.object({
847
+ var referenceSnapshotSchema = z3.object({
576
848
  revision: revisionSchema.nonnegative(),
577
- targets: z.array(resourceSchema).max(MAX_TARGETS),
578
- status: z.object({ state: z.enum(["synced", "pending", "degraded", "blocked"]), error: z.string().max(4096).nullable() })
849
+ targets: z3.array(resourceSchema).max(MAX_TARGETS),
850
+ status: z3.object({ state: z3.enum(["synced", "pending", "degraded", "blocked"]), error: z3.string().max(4096).nullable() })
579
851
  });
580
852
 
581
853
  // src/react.tsx
package/dist/testing.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/testing.ts
2
2
  import { canonicalizeIdentity, normalizeProjectionCommand, resourceIdentityOf } from "./index.js";
3
- import { createCrossReferencesClient } from "./bb.js";
3
+ import { createCrossReferencesClient, createCrossReferencesV2Client } from "./bb.js";
4
4
  async function runCrossReferencesConformance(options) {
5
5
  const command = normalizeProjectionCommand(options.command);
6
6
  if (command.tombstone || command.targets.length === 0)
@@ -43,6 +43,23 @@ async function runCrossReferencesConformance(options) {
43
43
  checks.push("backlinks-acceptance");
44
44
  return { level: "source-conformance", pluginId: client.pluginId, checks };
45
45
  }
46
+ async function runCrossReferencesV2Conformance(options) {
47
+ const client = createCrossReferencesV2Client(options.sdk, options.pluginId);
48
+ await client.describe();
49
+ const page = await client.listMentions(options.input);
50
+ if (page.status !== "page")
51
+ throw new Error("V2 fixture must yield a page.");
52
+ await options.assertPage(page);
53
+ const { cursor: _cursor, ifSnapshot: _conditional, ...base } = options.input;
54
+ const conditional = await client.listMentions({ ...base, ifSnapshot: page.snapshot });
55
+ if (conditional.status !== "not-modified" || !conditional.coverage.authoredUrlCoverage.watermark)
56
+ throw new Error("V2 conditional omitted current coverage.");
57
+ const lookup = await client.resolveLookup(options.lookup);
58
+ if (!["ready", "ambiguous", "incomplete"].includes(lookup.state) || lookup.options.length === 0)
59
+ throw new Error("V2 lookup fixture did not resolve.");
60
+ return { level: "source-conformance", pluginId: client.pluginId, checks: ["describe-v2", "actual-evidence-page", "conditional-current-coverage", "query-normalization"] };
61
+ }
46
62
  export {
63
+ runCrossReferencesV2Conformance,
47
64
  runCrossReferencesConformance
48
65
  };