@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/CONTRACT.md +158 -0
- package/README.md +29 -0
- package/dist/bb.js +403 -58
- package/dist/index.js +358 -56
- package/dist/react.js +328 -56
- package/dist/testing.js +18 -1
- package/dist/types/bb.d.ts +509 -1
- package/dist/types/evidence-v2.d.ts +1080 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/lookup.d.ts +10 -0
- package/dist/types/recognition.d.ts +29 -0
- package/dist/types/testing.d.ts +11 -0
- package/package.json +4 -3
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 =
|
|
443
|
-
label:
|
|
444
|
-
detail:
|
|
445
|
-
url:
|
|
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 =
|
|
454
|
-
provider:
|
|
455
|
-
keys:
|
|
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 =
|
|
465
|
-
provider:
|
|
466
|
-
keys:
|
|
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 =
|
|
475
|
-
var mutationIdSchema =
|
|
476
|
-
var revisionSchema = safeInteger(
|
|
477
|
-
var applyProjectionInputSchema =
|
|
478
|
-
protocolVersion:
|
|
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:
|
|
485
|
-
tombstone:
|
|
486
|
-
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 =
|
|
495
|
-
outcome:
|
|
766
|
+
var applyProjectionResponseSchema = z3.object({
|
|
767
|
+
outcome: z3.enum(["applied", "duplicate", "equal", "stale", "conflict", "cas-mismatch"]),
|
|
496
768
|
currentRevision: revisionSchema.nonnegative(),
|
|
497
|
-
currentDigest:
|
|
769
|
+
currentDigest: z3.string().regex(digestPattern).nullable()
|
|
498
770
|
}).strict();
|
|
499
|
-
var projectionSchema =
|
|
771
|
+
var projectionSchema = z3.object({
|
|
500
772
|
producerPluginId: producerPluginIdSchema,
|
|
501
773
|
source: resourceSchema,
|
|
502
774
|
revision: revisionSchema.nonnegative(),
|
|
503
775
|
mutationId: mutationIdSchema,
|
|
504
|
-
payloadDigest:
|
|
505
|
-
tombstone:
|
|
506
|
-
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 =
|
|
780
|
+
var getProjectionInputSchema = z3.object({
|
|
509
781
|
producerPluginId: producerPluginIdSchema,
|
|
510
782
|
source: resourceIdentitySchema
|
|
511
783
|
}).strict();
|
|
512
|
-
var getProjectionOutputSchema =
|
|
513
|
-
var backlinkRowSchema =
|
|
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:
|
|
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 =
|
|
793
|
+
var listBacklinksInputSchema = z3.object({
|
|
522
794
|
target: resourceIdentitySchema,
|
|
523
|
-
pageSize:
|
|
524
|
-
cursor:
|
|
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 =
|
|
527
|
-
rows:
|
|
798
|
+
var listBacklinksOutputSchema = z3.object({
|
|
799
|
+
rows: z3.array(backlinkRowSchema).max(100),
|
|
528
800
|
total: revisionSchema.nonnegative(),
|
|
529
|
-
nextCursor:
|
|
801
|
+
nextCursor: z3.string().max(4096).nullable()
|
|
530
802
|
}).strict();
|
|
531
|
-
var forwardReferenceRowSchema =
|
|
803
|
+
var forwardReferenceRowSchema = z3.object({
|
|
532
804
|
target: resourceSchema,
|
|
533
805
|
producerPluginId: producerPluginIdSchema,
|
|
534
806
|
revision: revisionSchema.nonnegative(),
|
|
535
|
-
position:
|
|
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 =
|
|
810
|
+
var listForwardReferencesInputSchema = z3.object({
|
|
539
811
|
source: resourceIdentitySchema,
|
|
540
812
|
producerPluginId: producerPluginIdSchema.optional(),
|
|
541
|
-
pageSize:
|
|
542
|
-
cursor:
|
|
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 =
|
|
545
|
-
rows:
|
|
816
|
+
var listForwardReferencesOutputSchema = z3.object({
|
|
817
|
+
rows: z3.array(forwardReferenceRowSchema).max(100),
|
|
546
818
|
total: revisionSchema.nonnegative(),
|
|
547
|
-
nextCursor:
|
|
819
|
+
nextCursor: z3.string().max(4096).nullable()
|
|
548
820
|
}).strict();
|
|
549
|
-
var checkForwardReferencesInputSchema =
|
|
821
|
+
var checkForwardReferencesInputSchema = z3.object({
|
|
550
822
|
source: resourceIdentitySchema,
|
|
551
823
|
producerPluginId: producerPluginIdSchema.optional()
|
|
552
824
|
}).strict();
|
|
553
|
-
var forwardReferenceStatusSchema =
|
|
554
|
-
url:
|
|
555
|
-
status:
|
|
556
|
-
label:
|
|
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 =
|
|
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 =
|
|
563
|
-
var describeOutputSchema =
|
|
564
|
-
protocol:
|
|
565
|
-
versions:
|
|
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 =
|
|
847
|
+
var referenceSnapshotSchema = z3.object({
|
|
576
848
|
revision: revisionSchema.nonnegative(),
|
|
577
|
-
targets:
|
|
578
|
-
status:
|
|
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
|
};
|