PageSourceSearch

https://zaiye.art/yucang/prompt-vault-publish-bridge.mjs?v=20260826-handoff2

js zaiye.art collected 2026-10-02 01:16:05 UTC 3,735 bytes, 106 lines download raw bytes

1const TYPE = "prompt-vault-yucang-publish";
2const PROTOCOL_VERSION = 1;
3const EXTENSION_IDS = Object.freeze([
4  "fapladhajicfoiadhcpmbmfkodekkckg",
5  "idiemjhonlahnlnalpanhplbgjcfbpnl",
6]);
7
8function requestId() {
9  return crypto.randomUUID();
10}
11
12function uuid(value) {
13  return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
14}
15
16export function stableHandoffStringify(value) {
17  if (Array.isArray(value)) return `[${value.map(stableHandoffStringify).join(",")}]`;
18  if (value && typeof value === "object") {
19    return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableHandoffStringify(value[key])}`).join(",")}}`;
20  }
21  return JSON.stringify(value);
22}
23
24export async function hashHandoffContent(content) {
25  const bytes = new TextEncoder().encode(stableHandoffStringify(content));
26  const digest = await crypto.subtle.digest("SHA-256", bytes);
27  return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
28}
29
30function send(extensionId, message) {
31  return new Promise((resolve, reject) => {
32    if (!globalThis.chrome?.runtime?.sendMessage) return reject(new Error("prompt_vault_not_installed"));
33    chrome.runtime.sendMessage(extensionId, message, (response) => {
34      const lastError = chrome.runtime.lastError;
35      if (lastError) reject(new Error(lastError.message || "prompt_vault_unreachable"));
36      else resolve(response);
37    });
38  });
39}
40
41export function createPromptVaultPublishBridge() {
42  return {
43    async claim(handoffId) {
44      if (!uuid(handoffId)) throw new Error("invalid_handoff_id");
45      const claimRequestId = requestId();
46      let lastError = new Error("prompt_vault_not_installed");
47      for (const extensionId of EXTENSION_IDS) {
48        try {
49          const response = await send(extensionId, {
50            type: TYPE,
51            protocolVersion: PROTOCOL_VERSION,
52            action: "claim",
53            requestId: claimRequestId,
54            handoffId,
55          });
56          if (!response?.ok) throw new Error(response?.error || "claim_failed");
57          if (response.requestId !== claimRequestId || response.handoffId !== handoffId
58            || !response.content || typeof response.payloadHash !== "string") {
59            throw new Error("invalid_claim_response");
60          }
61          return { extensionId, requestId: claimRequestId, handoffId, ...response };
62        } catch (error) {
63          lastError = error;
64        }
65      }
66      throw lastError;
67    },
68
69    async complete(claim, result) {
70      const response = await send(claim.extensionId, {
71        type: TYPE,
72        protocolVersion: PROTOCOL_VERSION,
73        action: "complete",
74        requestId: claim.requestId,
75        handoffId: claim.handoffId,
76        workId: result.workId,
77        versionId: result.versionId,
78        status: result.status,
79      });
80      if (!response?.ok || response.requestId !== claim.requestId || response.handoffId !== claim.handoffId) {
81        throw new Error(response?.error || "complete_failed");
82      }
83      return response;
84    },
85
86    async discard(claim) {
87      const response = await send(claim.extensionId, {
88        type: TYPE,
89        protocolVersion: PROTOCOL_VERSION,
90        action: "discard",
91        requestId: claim.requestId,
92        handoffId: claim.handoffId,
93      });
94      if (!response?.ok || response.requestId !== claim.requestId || response.handoffId !== claim.handoffId) {
95        throw new Error(response?.error || "discard_failed");
96      }
97      return response;
98    },
99  };
100}
101
102export const PUBLISH_HANDOFF_PROTOCOL = Object.freeze({
103  type: TYPE,
104  protocolVersion: PROTOCOL_VERSION,
105  extensionIds: EXTENSION_IDS,
106});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.