@averyyy/pi-coding-agent 0.82.1-piclient.3 → 0.82.1-piclient.5
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/CHANGELOG.md +12 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +2 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/tool-effects.d.ts +6 -0
- package/dist/cli/tool-effects.d.ts.map +1 -0
- package/dist/cli/tool-effects.js +164 -0
- package/dist/cli/tool-effects.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +5 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +314 -89
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/pi-server-client.d.ts +53 -2
- package/dist/core/pi-server-client.d.ts.map +1 -1
- package/dist/core/pi-server-client.js +2082 -290
- package/dist/core/pi-server-client.js.map +1 -1
- package/dist/core/pi-server-compact-state.d.ts +81 -0
- package/dist/core/pi-server-compact-state.d.ts.map +1 -0
- package/dist/core/pi-server-compact-state.js +438 -0
- package/dist/core/pi-server-compact-state.js.map +1 -0
- package/dist/core/pi-server-protocol.d.ts +2 -0
- package/dist/core/pi-server-protocol.d.ts.map +1 -1
- package/dist/core/pi-server-protocol.js +24 -1
- package/dist/core/pi-server-protocol.js.map +1 -1
- package/dist/core/pi-server-request.d.ts +28 -0
- package/dist/core/pi-server-request.d.ts.map +1 -1
- package/dist/core/pi-server-request.js +492 -75
- package/dist/core/pi-server-request.js.map +1 -1
- package/dist/core/pi-server-run-state.d.ts +41 -0
- package/dist/core/pi-server-run-state.d.ts.map +1 -0
- package/dist/core/pi-server-run-state.js +318 -0
- package/dist/core/pi-server-run-state.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +69 -53
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +86 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +737 -144
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tool-effect-journal.d.ts +103 -0
- package/dist/core/tool-effect-journal.d.ts.map +1 -0
- package/dist/core/tool-effect-journal.js +1442 -0
- package/dist/core/tool-effect-journal.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts +3 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +46 -26
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +15 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +98 -29
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi-server-request.js","sourceRoot":"","sources":["../../src/core/pi-server-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,sBAAsB,GAAG,GAAG,CAAC;AACnC,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAC5C,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAwBnC,SAAS,cAAc,CAAC,KAAc,EAAU;IAC/C,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;AAAA,CACzD;AAED,MAAM,UAAU,kBAAkB,GAAW;IAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IACjD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,sBAAsB,GAAG,IAAI,CAAC;IAE1E,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;AAAA,CAChC;AAED,SAAS,WAAW,CAAC,SAAiB,EAA0B;IAC/D,OAAO;QACN,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC;AAAA,CACF;AAED,SAAS,MAAM,CAAC,KAAa,EAAU;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CACxD;AAED,SAAS,QAAQ,CAAC,KAAc,EAAoC;IACnE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAAA,CACnD;AAED,SAAS,cAAc,CAAC,KAAc,EAAyB;IAC9D,OAAO,CACN,QAAQ,CAAC,KAAK,CAAC,IAAI,UAAU,IAAI,KAAK,IAAI,WAAW,IAAI,KAAK,IAAI,YAAY,IAAI,KAAK,IAAI,aAAa,IAAI,KAAK,CACjH,CAAC;AAAA,CACF;AAED,KAAK,UAAU,UAAU,CACxB,QAAkB,EAClB,SAAiB,EACjB,UAAkB,EAClB,WAAmB,EACA;IACnB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC;QAAE,OAAO,KAAK,CAAC;IACtF,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAY,CAAC;QACxD,OAAO,CACN,cAAc,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,QAAQ,KAAK,IAAI;YACtB,IAAI,CAAC,SAAS,KAAK,SAAS;YAC5B,IAAI,CAAC,UAAU,KAAK,UAAU;YAC9B,IAAI,CAAC,WAAW,KAAK,WAAW,CAChC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AAAA,CACD;AAED,SAAS,aAAa,CACrB,MAAc,EACd,SAAiB,EACjB,aAAqB,EACrB,WAAmB,EACnB,QAAgB,EACN;IACV,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,CAAC;IACrD,MAAM,IAAI,GAAc;QACvB,SAAS;QACT,MAAM;QACN,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;QAClC,WAAW,EAAE,KAAK;QAClB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;KACvD,CAAC;IACF,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;AAAA,CACxC;AAED,SAAS,gBAAgB,CAAC,MAAc,EAAE,SAAiB,EAAE,OAAe,EAAE,QAAgB,EAAY;IACzG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACxF,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;YACrE,IAAI,GAAG,GAAG,CAAC;YACX,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACP,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC;QAChB,CAAC;IACF,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED,MAAM,OAAO,YAAY;IACxB,OAAO,CAAyB;IAEhC,YAAY,OAA+B,EAAE;QAC5C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAAA,CACvB;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAqB;QAClD,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,QAAQ,EAAE,EAAE;YACpD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAC5C,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;SAC3B,CAAC,CAAC;IAAA,CACH;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAa,EAAqB;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;QACtC,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QACxE,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,aAAmC,CAAC;QACxC,IAAI,eAAqC,CAAC;QAE1C,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE,CAAC;YAC/C,OAAO,SAAS,GAAG,MAAM,CAAC,MAAM,IAAI,aAAa,KAAK,SAAS,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBAClG,MAAM,KAAK,GAAG,SAAS,CAAC;gBACxB,SAAS,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5B,MAAM,SAAS,GAAc;oBAC5B,SAAS;oBACT,MAAM,EAAE,QAAQ;oBAChB,UAAU,EAAE,KAAK;oBACjB,WAAW,EAAE,MAAM,CAAC,MAAM;oBAC1B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC;oBACrB,KAAK;iBACL,CAAC;gBACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;gBACpF,IAAI,aAAa,KAAK,SAAS,IAAI,eAAe,KAAK,SAAS;oBAAE,OAAO;gBACzE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBAClB,eAAe,GAAG,QAAQ,CAAC;oBAC3B,OAAO;gBACR,CAAC;gBACD,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;oBACpE,aAAa,GAAG,QAAQ,CAAC;oBACzB,OAAO;gBACR,CAAC;YACF,CAAC;QAAA,CACD,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAC/F,CAAC;QAEF,IAAI,eAAe;YAAE,OAAO,eAAe,CAAC;QAC5C,IAAI,aAAa;YAAE,OAAO,aAAa,CAAC;QAExC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAAA,CACnE;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,OAAe,EAAqB;QACxE,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,QAAQ,EAAE,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAC5C,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;SAC3B,CAAC,CAAC;IAAA,CACH;CACD","sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { createHash, randomUUID } from \"node:crypto\";\n\nconst DEFAULT_MAX_REQUEST_KB = 512;\nconst CHUNK_ENDPOINT = \"/api/request/chunk\";\nconst CHUNK_UPLOAD_CONCURRENCY = 4;\n\nexport interface PiServerRequestOptions {\n\tserverUrl: string;\n\tauthToken: string;\n\tsignal?: AbortSignal;\n}\n\ninterface ChunkBody {\n\trequestId: string;\n\ttarget: string;\n\tchunkIndex: number;\n\ttotalChunks: number;\n\tsha256: string;\n\tchunk: string;\n}\n\ninterface ChunkAckBody {\n\treceived: unknown;\n\trequestId: unknown;\n\tchunkIndex: unknown;\n\ttotalChunks: unknown;\n}\n\nfunction jsonByteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf-8\");\n}\n\nexport function getMaxRequestBytes(): number {\n\tconst raw = process.env.PI_CLIENT_MAX_REQUEST_KB;\n\tif (raw === undefined || raw === \"\") return DEFAULT_MAX_REQUEST_KB * 1024;\n\n\tconst value = Number(raw);\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tthrow new Error(\"PI_CLIENT_MAX_REQUEST_KB must be a positive number\");\n\t}\n\treturn Math.floor(value * 1024);\n}\n\nfunction makeHeaders(authToken: string): Record<string, string> {\n\treturn {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n\t};\n}\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isChunkAckBody(value: unknown): value is ChunkAckBody {\n\treturn (\n\t\tisRecord(value) && \"received\" in value && \"requestId\" in value && \"chunkIndex\" in value && \"totalChunks\" in value\n\t);\n}\n\nasync function isChunkAck(\n\tresponse: Response,\n\trequestId: string,\n\tchunkIndex: number,\n\ttotalChunks: number,\n): Promise<boolean> {\n\tif (!response.headers.get(\"Content-Type\")?.includes(\"application/json\")) return false;\n\ttry {\n\t\tconst body = (await response.clone().json()) as unknown;\n\t\treturn (\n\t\t\tisChunkAckBody(body) &&\n\t\t\tbody.received === true &&\n\t\t\tbody.requestId === requestId &&\n\t\t\tbody.chunkIndex === chunkIndex &&\n\t\t\tbody.totalChunks === totalChunks\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction chunkBodyFits(\n\ttarget: string,\n\trequestId: string,\n\tencodedLength: number,\n\tchunkLength: number,\n\tmaxBytes: number,\n): boolean {\n\tconst total = Math.ceil(encodedLength / chunkLength);\n\tconst body: ChunkBody = {\n\t\trequestId,\n\t\ttarget,\n\t\tchunkIndex: Math.max(0, total - 1),\n\t\ttotalChunks: total,\n\t\tsha256: \"0\".repeat(64),\n\t\tchunk: \"x\".repeat(Math.min(chunkLength, encodedLength)),\n\t};\n\treturn jsonByteLength(body) <= maxBytes;\n}\n\nfunction splitEncodedBody(target: string, requestId: string, encoded: string, maxBytes: number): string[] {\n\tif (!chunkBodyFits(target, requestId, encoded.length, 1, maxBytes)) {\n\t\tthrow new Error(\"PI_CLIENT_MAX_REQUEST_KB is too small for pi-server chunk envelopes\");\n\t}\n\n\tlet low = 1;\n\tlet high = encoded.length;\n\tlet best = 1;\n\twhile (low <= high) {\n\t\tconst mid = Math.floor((low + high) / 2);\n\t\tif (chunkBodyFits(target, requestId, encoded.length, mid, maxBytes)) {\n\t\t\tbest = mid;\n\t\t\tlow = mid + 1;\n\t\t} else {\n\t\t\thigh = mid - 1;\n\t\t}\n\t}\n\n\tconst chunks: string[] = [];\n\tfor (let offset = 0; offset < encoded.length; offset += best) {\n\t\tchunks.push(encoded.slice(offset, offset + best));\n\t}\n\treturn chunks;\n}\n\nexport class ChunkRequest {\n\toptions: PiServerRequestOptions;\n\n\tconstructor(options: PiServerRequestOptions) {\n\t\tthis.options = options;\n\t}\n\n\tasync getJson(endpoint: string): Promise<Response> {\n\t\treturn fetch(`${this.options.serverUrl}${endpoint}`, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: makeHeaders(this.options.authToken),\n\t\t\tsignal: this.options.signal,\n\t\t});\n\t}\n\n\tasync postJson(endpoint: string, body: unknown): Promise<Response> {\n\t\tconst rawJson = JSON.stringify(body);\n\t\tconst maxBytes = getMaxRequestBytes();\n\t\tif (Buffer.byteLength(rawJson, \"utf-8\") <= maxBytes) {\n\t\t\treturn this.#postRawJson(endpoint, rawJson);\n\t\t}\n\n\t\tconst requestId = randomUUID();\n\t\tconst encoded = Buffer.from(rawJson, \"utf-8\").toString(\"base64\");\n\t\tconst chunks = splitEncodedBody(endpoint, requestId, encoded, maxBytes);\n\t\tlet nextIndex = 0;\n\t\tlet finalResponse: Response | undefined;\n\t\tlet failureResponse: Response | undefined;\n\n\t\tconst uploadWorker = async (): Promise<void> => {\n\t\t\twhile (nextIndex < chunks.length && finalResponse === undefined && failureResponse === undefined) {\n\t\t\t\tconst index = nextIndex;\n\t\t\t\tnextIndex++;\n\t\t\t\tconst chunk = chunks[index];\n\t\t\t\tconst chunkBody: ChunkBody = {\n\t\t\t\t\trequestId,\n\t\t\t\t\ttarget: endpoint,\n\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\ttotalChunks: chunks.length,\n\t\t\t\t\tsha256: sha256(chunk),\n\t\t\t\t\tchunk,\n\t\t\t\t};\n\t\t\t\tconst response = await this.#postRawJson(CHUNK_ENDPOINT, JSON.stringify(chunkBody));\n\t\t\t\tif (finalResponse !== undefined || failureResponse !== undefined) return;\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tfailureResponse = response;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!(await isChunkAck(response, requestId, index, chunks.length))) {\n\t\t\t\t\tfinalResponse = response;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tawait Promise.all(\n\t\t\tArray.from({ length: Math.min(CHUNK_UPLOAD_CONCURRENCY, chunks.length) }, () => uploadWorker()),\n\t\t);\n\n\t\tif (failureResponse) return failureResponse;\n\t\tif (finalResponse) return finalResponse;\n\n\t\tthrow new Error(\"No final chunk response received from pi-server\");\n\t}\n\n\tasync #postRawJson(endpoint: string, rawJson: string): Promise<Response> {\n\t\treturn fetch(`${this.options.serverUrl}${endpoint}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: makeHeaders(this.options.authToken),\n\t\t\tbody: rawJson,\n\t\t\tsignal: this.options.signal,\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pi-server-request.js","sourceRoot":"","sources":["../../src/core/pi-server-request.ts"],"names":[],"mappings":"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","sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { createHash, randomUUID } from \"node:crypto\";\n\nconst DEFAULT_MAX_REQUEST_KB = 512;\nconst CHUNK_ENDPOINT = \"/api/request/chunk\";\nconst CHUNK_UPLOAD_CONCURRENCY = 4;\nconst CHUNK_MAX_TOTAL_CHUNKS = 4096;\nconst CHUNK_UPLOAD_RETRY_DELAYS_MS = [100, 250, 500] as const;\nconst LEGACY_CHUNK_ACK_MAX_BYTES = 4096;\nconst DEFAULT_CHUNK_REQUEST_MEMO_LIMIT = 128;\nconst DEFAULT_RESPONSE_NO_PROGRESS_TIMEOUT_MS = 90_000;\nexport const PI_SERVER_CHUNK_ACK_HEADER = \"X-Pi-Chunk-Ack\";\nexport const PI_SERVER_CHUNK_ACK_VALUE = \"1\";\nexport const PI_SERVER_CHUNK_FINAL_VALUE = \"0\";\nexport const PI_SERVER_CHUNK_SEGMENT_ENCODING = \"base64-segment-v1\";\nexport const PI_SERVER_RESPONSE_HEADER_TIMEOUT_MS = 30_000;\n\nexport interface PiServerRequestOptions {\n\tserverUrl: string;\n\tauthToken: string;\n\tsignal?: AbortSignal;\n\tresponseHeaderTimeoutMs?: number;\n\tmaxChunkRequestMemos?: number;\n}\n\ninterface ChunkBody {\n\trequestId: string;\n\ttarget: string;\n\tchunkIndex: number;\n\ttotalChunks: number;\n\tsha256: string;\n\tchunk: string;\n\tencoding: typeof PI_SERVER_CHUNK_SEGMENT_ENCODING;\n\trawTotalBytes: number;\n\trawChunkBytes: number;\n}\n\ninterface ChunkAckBody {\n\treceived: unknown;\n\trequestId: unknown;\n\tchunkIndex: unknown;\n\ttotalChunks: unknown;\n}\n\ninterface ChunkRequestMemo {\n\trequestId: string;\n\tmaxBytes: number;\n}\n\ninterface ChunkResponseInspection {\n\tacknowledged: boolean;\n\tresponse?: Response;\n}\n\ninterface BodyNoProgressState {\n\treadonly timeoutMs: number;\n\tdeadlineMs: number;\n}\n\nexport class PiServerTransportHeaderTimeoutError extends Error {\n\treadonly code = \"PI_SERVER_TRANSPORT_HEADER_TIMEOUT\";\n\treadonly timeoutMs: number;\n\n\tconstructor(method: string, endpoint: string, timeoutMs: number) {\n\t\tsuper(`pi-server transport header timeout after ${timeoutMs} ms (ETIMEDOUT): ${method} ${endpoint}`);\n\t\tthis.name = \"PiServerTransportHeaderTimeoutError\";\n\t\tthis.timeoutMs = timeoutMs;\n\t}\n}\n\nclass PiServerTransportBodyNoProgressError extends Error {\n\tconstructor(timeoutMs: number) {\n\t\tsuper(`pi-server response made no progress for ${timeoutMs}ms`);\n\t\tthis.name = \"PiServerTransportBodyNoProgressError\";\n\t}\n}\n\nexport class PiServerChunkRequestMemoLimitError extends Error {\n\treadonly code = \"PI_SERVER_CHUNK_REQUEST_MEMO_LIMIT\";\n\treadonly limit: number;\n\n\tconstructor(limit: number) {\n\t\tsuper(\n\t\t\t`pi-server chunk request identity limit (${limit}) reached; refusing to allocate a new requestId while prior requests remain uncertain`,\n\t\t);\n\t\tthis.name = \"PiServerChunkRequestMemoLimitError\";\n\t\tthis.limit = limit;\n\t}\n}\n\nexport class PiServerChunkAckProtocolError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"PiServerChunkAckProtocolError\";\n\t}\n}\n\nexport class PiServerTransportBodyLimitError extends Error {\n\treadonly code = \"PI_SERVER_TRANSPORT_BODY_LIMIT\";\n\treadonly maxBytes: number;\n\n\tconstructor(maxBytes: number) {\n\t\tsuper(`pi-server response body exceeded ${maxBytes} bytes`);\n\t\tthis.name = \"PiServerTransportBodyLimitError\";\n\t\tthis.maxBytes = maxBytes;\n\t}\n}\n\nfunction jsonByteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf-8\");\n}\n\nexport function getMaxRequestBytes(): number {\n\tconst raw = process.env.PI_CLIENT_MAX_REQUEST_KB;\n\tif (raw === undefined || raw === \"\") return DEFAULT_MAX_REQUEST_KB * 1024;\n\n\tconst value = Number(raw);\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tthrow new Error(\"PI_CLIENT_MAX_REQUEST_KB must be a positive number\");\n\t}\n\treturn Math.floor(value * 1024);\n}\n\nfunction makeHeaders(authToken: string): Record<string, string> {\n\treturn {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n\t};\n}\n\nfunction sha256(value: string | Uint8Array): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction isTransientChunkResponse(status: number): boolean {\n\treturn status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\nfunction waitForChunkRetry(delayMs: number, signal?: AbortSignal): Promise<void> {\n\tif (signal?.aborted) return Promise.reject(signal.reason);\n\n\treturn new Promise((resolve, reject) => {\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, delayMs);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\treject(signal?.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\"));\n\t\t};\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isChunkAckBody(value: unknown): value is ChunkAckBody {\n\treturn (\n\t\tisRecord(value) && \"received\" in value && \"requestId\" in value && \"chunkIndex\" in value && \"totalChunks\" in value\n\t);\n}\n\nfunction getResponseNoProgressTimeoutMs(): number {\n\tconst raw = process.env.PI_SERVER_RESPONSE_NO_PROGRESS_TIMEOUT_MS;\n\tconst value = raw === undefined ? DEFAULT_RESPONSE_NO_PROGRESS_TIMEOUT_MS : Number(raw);\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tthrow new Error(\"PI_SERVER_RESPONSE_NO_PROGRESS_TIMEOUT_MS must be positive finite milliseconds\");\n\t}\n\treturn value;\n}\n\nfunction createBodyNoProgressState(): BodyNoProgressState {\n\tconst timeoutMs = getResponseNoProgressTimeoutMs();\n\treturn { timeoutMs, deadlineMs: Date.now() + timeoutMs };\n}\n\nasync function readPiServerBodyChunk(\n\treader: ReadableStreamDefaultReader<Uint8Array>,\n\tstate: BodyNoProgressState,\n): Promise<Awaited<ReturnType<ReadableStreamDefaultReader<Uint8Array>[\"read\"]>>> {\n\twhile (true) {\n\t\tconst remainingMs = state.deadlineMs - Date.now();\n\t\tif (remainingMs <= 0) {\n\t\t\tthrow new PiServerTransportBodyNoProgressError(state.timeoutMs);\n\t\t}\n\t\tconst result = await new Promise<Awaited<ReturnType<ReadableStreamDefaultReader<Uint8Array>[\"read\"]>>>(\n\t\t\t(resolve, reject) => {\n\t\t\t\tlet settled = false;\n\t\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(new PiServerTransportBodyNoProgressError(state.timeoutMs));\n\t\t\t\t}, remainingMs);\n\t\t\t\ttimeout.unref();\n\t\t\t\tvoid reader.read().then(\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tif (settled) return;\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\t\tresolve(value);\n\t\t\t\t\t},\n\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\tif (settled) return;\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\t\treject(error);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t},\n\t\t);\n\t\tif (result.done || result.value.byteLength > 0) {\n\t\t\tif (!result.done) state.deadlineMs = Date.now() + state.timeoutMs;\n\t\t\treturn result;\n\t\t}\n\t\tawait new Promise<void>((resolve) => {\n\t\t\tsetTimeout(resolve, 0);\n\t\t});\n\t}\n}\n\nexport async function readPiServerResponseText(\n\tresponse: Response,\n\tmaxBytes = Number.POSITIVE_INFINITY,\n): Promise<string> {\n\tif (\n\t\t(maxBytes !== Number.POSITIVE_INFINITY && (!Number.isSafeInteger(maxBytes) || maxBytes <= 0)) ||\n\t\tmaxBytes === Number.NEGATIVE_INFINITY\n\t) {\n\t\tthrow new Error(\"pi-server response body limit must be positive safe-integer bytes or Infinity\");\n\t}\n\tif (!response.body) throw new Error(\"pi-server response body was missing\");\n\tconst reader = response.body.getReader();\n\tconst decoder = new TextDecoder();\n\tconst noProgress = createBodyNoProgressState();\n\tlet body = \"\";\n\tlet bodyBytes = 0;\n\ttry {\n\t\twhile (true) {\n\t\t\tconst result = await readPiServerBodyChunk(reader, noProgress);\n\t\t\tif (result.done) {\n\t\t\t\tbody += decoder.decode();\n\t\t\t\treturn body;\n\t\t\t}\n\t\t\tbodyBytes += result.value.byteLength;\n\t\t\tif (bodyBytes > maxBytes) {\n\t\t\t\tthrow new PiServerTransportBodyLimitError(maxBytes);\n\t\t\t}\n\t\t\tbody += decoder.decode(result.value, { stream: true });\n\t\t}\n\t} catch (error) {\n\t\tvoid reader.cancel().catch(() => undefined);\n\t\tthrow error;\n\t}\n}\n\nexport async function readPiServerResponseJson(\n\tresponse: Response,\n\tmaxBytes = Number.POSITIVE_INFINITY,\n): Promise<unknown> {\n\treturn JSON.parse(await readPiServerResponseText(response, maxBytes)) as unknown;\n}\n\nfunction rebuildResponse(response: Response, body: ConstructorParameters<typeof Response>[0]): Response {\n\treturn new Response(body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: response.headers,\n\t});\n}\n\nasync function discardResponse(response: Response | undefined): Promise<void> {\n\tif (!response?.body || response.bodyUsed || response.body.locked) return;\n\ttry {\n\t\tawait response.body.cancel();\n\t} catch {\n\t\t// The response is already unusable and must not replace the selected final response.\n\t}\n}\n\nasync function inspectLegacyChunkAck(\n\tresponse: Response,\n\trequestId: string,\n\tchunkIndex: number,\n\ttotalChunks: number,\n): Promise<ChunkResponseInspection> {\n\tconst contentLength = Number(response.headers.get(\"Content-Length\"));\n\tif (Number.isFinite(contentLength) && contentLength > LEGACY_CHUNK_ACK_MAX_BYTES) {\n\t\treturn { acknowledged: false, response };\n\t}\n\tif (!response.body) return { acknowledged: false, response };\n\tconst reader = response.body.getReader();\n\tconst noProgress = createBodyNoProgressState();\n\tconst chunks: Uint8Array[] = [];\n\tlet bodyBytes = 0;\n\ttry {\n\t\twhile (true) {\n\t\t\tconst result = await readPiServerBodyChunk(reader, noProgress);\n\t\t\tif (result.done) break;\n\t\t\tchunks.push(result.value);\n\t\t\tbodyBytes += result.value.byteLength;\n\t\t\tif (bodyBytes > LEGACY_CHUNK_ACK_MAX_BYTES) {\n\t\t\t\tlet prefixIndex = 0;\n\t\t\t\tconst rebuiltBody = new ReadableStream<Uint8Array>({\n\t\t\t\t\tasync pull(controller) {\n\t\t\t\t\t\tif (prefixIndex < chunks.length) {\n\t\t\t\t\t\t\tconst prefix = chunks[prefixIndex];\n\t\t\t\t\t\t\tchunks[prefixIndex] = new Uint8Array();\n\t\t\t\t\t\t\tprefixIndex++;\n\t\t\t\t\t\t\tcontroller.enqueue(prefix);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst next = await readPiServerBodyChunk(reader, noProgress);\n\t\t\t\t\t\t\tif (next.done) {\n\t\t\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontroller.enqueue(next.value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tcontroller.error(error);\n\t\t\t\t\t\t\tvoid reader.cancel(error).catch(() => undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcancel(reason) {\n\t\t\t\t\t\treturn reader.cancel(reason);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { acknowledged: false, response: rebuildResponse(response, rebuiltBody) };\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tvoid reader.cancel().catch(() => undefined);\n\t\tthrow error;\n\t}\n\n\tconst encoded = Buffer.concat(\n\t\tchunks.map((chunk) => Buffer.from(chunk)),\n\t\tbodyBytes,\n\t);\n\tconst rebuilt = rebuildResponse(response, encoded);\n\ttry {\n\t\tconst body = JSON.parse(encoded.toString(\"utf-8\")) as unknown;\n\t\tconst acknowledged =\n\t\t\tisChunkAckBody(body) &&\n\t\t\tbody.received === true &&\n\t\t\tbody.requestId === requestId &&\n\t\t\tbody.chunkIndex === chunkIndex &&\n\t\t\tbody.totalChunks === totalChunks;\n\t\treturn acknowledged ? { acknowledged: true } : { acknowledged: false, response: rebuilt };\n\t} catch {\n\t\treturn { acknowledged: false, response: rebuilt };\n\t}\n}\n\nasync function inspectChunkResponse(\n\tresponse: Response,\n\trequestId: string,\n\tchunkIndex: number,\n\ttotalChunks: number,\n): Promise<ChunkResponseInspection> {\n\tconst marker = response.headers.get(PI_SERVER_CHUNK_ACK_HEADER);\n\tif (marker === PI_SERVER_CHUNK_FINAL_VALUE) {\n\t\treturn { acknowledged: false, response };\n\t}\n\tif (marker === PI_SERVER_CHUNK_ACK_VALUE) {\n\t\tif (!response.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\tawait discardResponse(response);\n\t\t\tthrow new PiServerChunkAckProtocolError(\"pi-server chunk acknowledgement must use application/json\");\n\t\t}\n\t\tconst text = await readPiServerResponseText(response, LEGACY_CHUNK_ACK_MAX_BYTES);\n\t\tlet body: unknown;\n\t\ttry {\n\t\t\tbody = JSON.parse(text) as unknown;\n\t\t} catch {\n\t\t\tthrow new PiServerChunkAckProtocolError(\"pi-server chunk acknowledgement was not valid JSON\");\n\t\t}\n\t\tif (\n\t\t\t!isChunkAckBody(body) ||\n\t\t\tbody.received !== true ||\n\t\t\tbody.requestId !== requestId ||\n\t\t\tbody.chunkIndex !== chunkIndex ||\n\t\t\tbody.totalChunks !== totalChunks\n\t\t) {\n\t\t\tthrow new PiServerChunkAckProtocolError(\"pi-server chunk acknowledgement did not match its request envelope\");\n\t\t}\n\t\treturn { acknowledged: true };\n\t}\n\tif (marker !== null) {\n\t\tawait discardResponse(response);\n\t\tthrow new PiServerChunkAckProtocolError(\n\t\t\t`pi-server returned unsupported ${PI_SERVER_CHUNK_ACK_HEADER} value: ${marker}`,\n\t\t);\n\t}\n\tif (!response.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\treturn { acknowledged: false, response };\n\t}\n\treturn inspectLegacyChunkAck(response, requestId, chunkIndex, totalChunks);\n}\n\nfunction getRawChunkLayout(\n\ttarget: string,\n\trequestId: string,\n\trawBodyBytes: number,\n\tmaxBytes: number,\n): { rawChunkBytes: number; totalChunks: number } {\n\tlet totalChunks = 1;\n\twhile (true) {\n\t\tconst emptyEnvelopeBytes = jsonByteLength({\n\t\t\trequestId,\n\t\t\ttarget,\n\t\t\tchunkIndex: totalChunks - 1,\n\t\t\ttotalChunks,\n\t\t\tsha256: \"0\".repeat(64),\n\t\t\tchunk: \"\",\n\t\t\tencoding: PI_SERVER_CHUNK_SEGMENT_ENCODING,\n\t\t\trawTotalBytes: rawBodyBytes,\n\t\t\t// Using the total body size here is conservative because every\n\t\t\t// derived chunk size is no larger and therefore has no more digits.\n\t\t\trawChunkBytes: rawBodyBytes,\n\t\t} satisfies ChunkBody);\n\t\tconst encodedChunkBytes = Math.floor((maxBytes - emptyEnvelopeBytes) / 4) * 4;\n\t\tconst rawChunkBytes = Math.floor(encodedChunkBytes / 4) * 3;\n\t\tif (rawChunkBytes <= 0) {\n\t\t\tthrow new Error(\"PI_CLIENT_MAX_REQUEST_KB is too small for pi-server chunk envelopes\");\n\t\t}\n\t\tconst nextTotalChunks = Math.ceil(rawBodyBytes / rawChunkBytes);\n\t\tif (nextTotalChunks > CHUNK_MAX_TOTAL_CHUNKS) {\n\t\t\tthrow new Error(`pi-server chunk request exceeds the ${CHUNK_MAX_TOTAL_CHUNKS}-chunk protocol limit`);\n\t\t}\n\t\tif (nextTotalChunks === totalChunks) {\n\t\t\treturn { rawChunkBytes, totalChunks };\n\t\t}\n\t\tif (nextTotalChunks < totalChunks) {\n\t\t\tthrow new Error(\"pi-server chunk layout did not converge monotonically\");\n\t\t}\n\t\ttotalChunks = nextTotalChunks;\n\t}\n}\n\nexport class ChunkRequest {\n\toptions: PiServerRequestOptions;\n\treadonly #chunkRequestMemos = new Map<string, ChunkRequestMemo>();\n\treadonly #maxChunkRequestMemos: number;\n\n\tconstructor(options: PiServerRequestOptions) {\n\t\tconst maxChunkRequestMemos = options.maxChunkRequestMemos ?? DEFAULT_CHUNK_REQUEST_MEMO_LIMIT;\n\t\tif (!Number.isSafeInteger(maxChunkRequestMemos) || maxChunkRequestMemos <= 0) {\n\t\t\tthrow new Error(\"maxChunkRequestMemos must be a positive safe integer\");\n\t\t}\n\t\tthis.options = options;\n\t\tthis.#maxChunkRequestMemos = maxChunkRequestMemos;\n\t}\n\n\tasync getJson(endpoint: string): Promise<Response> {\n\t\treturn this.#fetchWithResponseHeaderTimeout(endpoint, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: makeHeaders(this.options.authToken),\n\t\t});\n\t}\n\n\tasync deleteJson(endpoint: string): Promise<Response> {\n\t\treturn this.#fetchWithResponseHeaderTimeout(endpoint, {\n\t\t\tmethod: \"DELETE\",\n\t\t\theaders: makeHeaders(this.options.authToken),\n\t\t});\n\t}\n\n\tasync postJson(endpoint: string, body: unknown): Promise<Response> {\n\t\tconst rawBody = Buffer.from(JSON.stringify(body), \"utf-8\");\n\t\tconst memoKey = `${endpoint}\\0${sha256(rawBody)}`;\n\t\tlet memo = this.#chunkRequestMemos.get(memoKey);\n\t\tconst maxBytes = memo?.maxBytes ?? getMaxRequestBytes();\n\t\tif (memo === undefined && rawBody.byteLength <= maxBytes) {\n\t\t\treturn this.#postRawJson(endpoint, rawBody.toString(\"utf-8\"));\n\t\t}\n\n\t\tif (memo === undefined) {\n\t\t\tif (this.#chunkRequestMemos.size >= this.#maxChunkRequestMemos) {\n\t\t\t\tthrow new PiServerChunkRequestMemoLimitError(this.#maxChunkRequestMemos);\n\t\t\t}\n\t\t\tmemo = { requestId: randomUUID(), maxBytes };\n\t\t\tthis.#chunkRequestMemos.set(memoKey, memo);\n\t\t}\n\n\t\tconst { requestId } = memo;\n\t\tlet layout: { rawChunkBytes: number; totalChunks: number };\n\t\ttry {\n\t\t\tlayout = getRawChunkLayout(endpoint, requestId, rawBody.byteLength, memo.maxBytes);\n\t\t} catch (error) {\n\t\t\tif (this.#chunkRequestMemos.get(memoKey) === memo) {\n\t\t\t\tthis.#chunkRequestMemos.delete(memoKey);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tlet nextIndex = 0;\n\t\tlet finalResponse: Response | undefined;\n\t\tlet transientFailureResponse: Response | undefined;\n\t\tlet fatalError: unknown;\n\n\t\tconst stopped = () => finalResponse !== undefined || fatalError !== undefined;\n\t\tconst replaceTransientFailureResponse = async (response: Response): Promise<void> => {\n\t\t\tconst previous = transientFailureResponse;\n\t\t\ttransientFailureResponse = response;\n\t\t\tif (previous !== response) await discardResponse(previous);\n\t\t};\n\n\t\tconst uploadChunk = async (index: number): Promise<void> => {\n\t\t\tconst start = index * layout.rawChunkBytes;\n\t\t\tconst chunk = rawBody\n\t\t\t\t.subarray(start, Math.min(start + layout.rawChunkBytes, rawBody.byteLength))\n\t\t\t\t.toString(\"base64\");\n\t\t\tlet lastError: unknown;\n\t\t\tlet lastTransientResponse: Response | undefined;\n\n\t\t\ttry {\n\t\t\t\tfor (let attempt = 0; attempt <= CHUNK_UPLOAD_RETRY_DELAYS_MS.length; attempt++) {\n\t\t\t\t\tif (stopped()) return;\n\t\t\t\t\tif (attempt > 0) {\n\t\t\t\t\t\tawait waitForChunkRetry(CHUNK_UPLOAD_RETRY_DELAYS_MS[attempt - 1], this.options.signal);\n\t\t\t\t\t\tif (stopped()) return;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst chunkBody: ChunkBody = {\n\t\t\t\t\t\trequestId,\n\t\t\t\t\t\ttarget: endpoint,\n\t\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\t\ttotalChunks: layout.totalChunks,\n\t\t\t\t\t\tsha256: sha256(chunk),\n\t\t\t\t\t\tchunk,\n\t\t\t\t\t\tencoding: PI_SERVER_CHUNK_SEGMENT_ENCODING,\n\t\t\t\t\t\trawTotalBytes: rawBody.byteLength,\n\t\t\t\t\t\trawChunkBytes: layout.rawChunkBytes,\n\t\t\t\t\t};\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet response = await this.#postRawJson(CHUNK_ENDPOINT, JSON.stringify(chunkBody));\n\t\t\t\t\t\tif (stopped()) {\n\t\t\t\t\t\t\tawait discardResponse(response);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (response.ok) {\n\t\t\t\t\t\t\tconst inspection = await inspectChunkResponse(response, requestId, index, layout.totalChunks);\n\t\t\t\t\t\t\tif (inspection.acknowledged) return;\n\t\t\t\t\t\t\tif (!inspection.response) {\n\t\t\t\t\t\t\t\tthrow new PiServerChunkAckProtocolError(\n\t\t\t\t\t\t\t\t\t\"pi-server chunk response inspection lost its response\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresponse = inspection.response;\n\t\t\t\t\t\t\tif (stopped()) {\n\t\t\t\t\t\t\t\tawait discardResponse(response);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isTransientChunkResponse(response.status)) {\n\t\t\t\t\t\t\tawait discardResponse(lastTransientResponse);\n\t\t\t\t\t\t\tlastTransientResponse = response;\n\t\t\t\t\t\t\tlastError = new Error(\n\t\t\t\t\t\t\t\t`pi-server chunk ${index + 1}/${layout.totalChunks} returned HTTP ${response.status}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (finalResponse === undefined && fatalError === undefined) {\n\t\t\t\t\t\t\tfinalResponse = response;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait discardResponse(response);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (this.options.signal?.aborted) {\n\t\t\t\t\t\t\tthrow this.options.signal.reason ?? error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\terror instanceof PiServerChunkAckProtocolError ||\n\t\t\t\t\t\t\terror instanceof PiServerTransportBodyLimitError\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tfatalError = error;\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlastError = error;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (lastTransientResponse !== undefined) {\n\t\t\t\t\tawait replaceTransientFailureResponse(lastTransientResponse);\n\t\t\t\t\tlastTransientResponse = undefined;\n\t\t\t\t}\n\t\t\t\tif (lastError instanceof Error) {\n\t\t\t\t\tthrow lastError;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`pi-server chunk ${index + 1}/${layout.totalChunks} failed after bounded retries`);\n\t\t\t} finally {\n\t\t\t\tif (stopped()) await discardResponse(lastTransientResponse);\n\t\t\t}\n\t\t};\n\n\t\tconst uploadWorker = async (): Promise<void> => {\n\t\t\twhile (!stopped()) {\n\t\t\t\tconst index = nextIndex;\n\t\t\t\tif (index >= layout.totalChunks) return;\n\t\t\t\tnextIndex++;\n\t\t\t\tawait uploadChunk(index);\n\t\t\t}\n\t\t};\n\n\t\tconst results = await Promise.allSettled(\n\t\t\tArray.from({ length: Math.min(CHUNK_UPLOAD_CONCURRENCY, layout.totalChunks) }, () => uploadWorker()),\n\t\t);\n\n\t\tif (fatalError !== undefined) {\n\t\t\tawait discardResponse(finalResponse);\n\t\t\tawait discardResponse(transientFailureResponse);\n\t\t\tthrow fatalError;\n\t\t}\n\t\tif (this.options.signal?.aborted) {\n\t\t\tawait discardResponse(finalResponse);\n\t\t\tawait discardResponse(transientFailureResponse);\n\t\t\tthrow this.options.signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n\t\t}\n\t\tif (finalResponse !== undefined) {\n\t\t\tawait discardResponse(transientFailureResponse);\n\t\t\tif (this.#chunkRequestMemos.get(memoKey) === memo) {\n\t\t\t\tthis.#chunkRequestMemos.delete(memoKey);\n\t\t\t}\n\t\t\treturn finalResponse;\n\t\t}\n\t\tif (transientFailureResponse !== undefined) {\n\t\t\treturn transientFailureResponse;\n\t\t}\n\t\tfor (const result of results) {\n\t\t\tif (result.status === \"rejected\") {\n\t\t\t\tthrow result.reason;\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\"No final chunk response received from pi-server\");\n\t}\n\n\tasync #postRawJson(endpoint: string, rawJson: string): Promise<Response> {\n\t\treturn this.#fetchWithResponseHeaderTimeout(endpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: makeHeaders(this.options.authToken),\n\t\t\tbody: rawJson,\n\t\t});\n\t}\n\n\tasync #fetchWithResponseHeaderTimeout(endpoint: string, init: RequestInit): Promise<Response> {\n\t\tconst timeoutMs = this.options.responseHeaderTimeoutMs ?? PI_SERVER_RESPONSE_HEADER_TIMEOUT_MS;\n\t\tif (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n\t\t\tthrow new Error(\"responseHeaderTimeoutMs must be a positive finite number\");\n\t\t}\n\n\t\tconst method = init.method ?? \"GET\";\n\t\tconst timeoutError = new PiServerTransportHeaderTimeoutError(method, endpoint, timeoutMs);\n\t\tconst timeoutController = new AbortController();\n\t\tconst signal = this.options.signal\n\t\t\t? AbortSignal.any([this.options.signal, timeoutController.signal])\n\t\t\t: timeoutController.signal;\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttimeoutController.abort(timeoutError);\n\t\t}, timeoutMs);\n\t\ttimeout.unref();\n\n\t\ttry {\n\t\t\treturn await fetch(`${this.options.serverUrl}${endpoint}`, {\n\t\t\t\t...init,\n\t\t\t\tsignal,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (timeoutController.signal.aborted && !this.options.signal?.aborted) {\n\t\t\t\tthrow timeoutError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
declare const RUN_STATE_VERSION = 1;
|
|
3
|
+
interface PiServerRunStateBase {
|
|
4
|
+
version: typeof RUN_STATE_VERSION;
|
|
5
|
+
sequence: number;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PiServerPendingRunState extends PiServerRunStateBase {
|
|
9
|
+
kind: "run";
|
|
10
|
+
serverHash: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
runId: string;
|
|
13
|
+
baseTreeHash: string;
|
|
14
|
+
baseEntryCount: number;
|
|
15
|
+
baseLeafId: string | null;
|
|
16
|
+
requestHash: string;
|
|
17
|
+
}
|
|
18
|
+
export interface WritePiServerPendingRunInput {
|
|
19
|
+
serverHash: string;
|
|
20
|
+
sessionId: string;
|
|
21
|
+
runId: string;
|
|
22
|
+
baseTreeHash: string;
|
|
23
|
+
baseEntryCount: number;
|
|
24
|
+
baseLeafId: string | null;
|
|
25
|
+
requestHash: string;
|
|
26
|
+
timestamp?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface PiServerRunStateLease {
|
|
29
|
+
readonly path: string;
|
|
30
|
+
readonly database: DatabaseSync;
|
|
31
|
+
active: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function acquirePiServerRunStateLease(path: string): PiServerRunStateLease;
|
|
34
|
+
export declare function releasePiServerRunStateLease(lease: PiServerRunStateLease): void;
|
|
35
|
+
export declare function getPiServerRunStatePath(sessionFile: string): string;
|
|
36
|
+
export declare function hashPiServerIdentity(serverUrl: string): string;
|
|
37
|
+
export declare function readPiServerPendingRun(path: string, lease?: PiServerRunStateLease): PiServerPendingRunState | undefined;
|
|
38
|
+
export declare function writePiServerPendingRun(path: string, input: WritePiServerPendingRunInput, lease?: PiServerRunStateLease): PiServerPendingRunState;
|
|
39
|
+
export declare function acknowledgePiServerPendingRun(path: string, runId: string, timestamp?: number, lease?: PiServerRunStateLease): void;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=pi-server-run-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-server-run-state.d.ts","sourceRoot":"","sources":["../../src/core/pi-server-run-state.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,QAAA,MAAM,iBAAiB,IAAI,CAAC;AAK5B,UAAU,oBAAoB;IAC7B,OAAO,EAAE,OAAO,iBAAiB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACpE,IAAI,EAAE,KAAK,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACpB;AAeD,MAAM,WAAW,4BAA4B;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAOD,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;CAChB;AAMD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CAuBhF;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAa/E;AAmMD,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC3B,uBAAuB,GAAG,SAAS,CAOrC;AAED,wBAAgB,uBAAuB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,4BAA4B,EACnC,KAAK,CAAC,EAAE,qBAAqB,GAC3B,uBAAuB,CAuCzB;AAED,wBAAgB,6BAA6B,CAC5C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,SAAa,EACtB,KAAK,CAAC,EAAE,qBAAqB,GAC3B,IAAI,CAiBN","sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { createHash } from \"node:crypto\";\nimport { closeSync, existsSync, fsyncSync, openSync, readFileSync, truncateSync, writeSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\n\nconst RUN_STATE_VERSION = 1;\nconst RUN_STATE_MAX_BYTES = 8 * 1024 * 1024;\nconst SHA256_PATTERN = /^[a-f0-9]{64}$/;\nconst IDENTIFIER_MAX_CHARS = 1024;\n\ninterface PiServerRunStateBase {\n\tversion: typeof RUN_STATE_VERSION;\n\tsequence: number;\n\ttimestamp: number;\n}\n\nexport interface PiServerPendingRunState extends PiServerRunStateBase {\n\tkind: \"run\";\n\tserverHash: string;\n\tsessionId: string;\n\trunId: string;\n\tbaseTreeHash: string;\n\tbaseEntryCount: number;\n\tbaseLeafId: string | null;\n\trequestHash: string;\n}\n\ninterface PiServerAcknowledgedRunState extends PiServerRunStateBase {\n\tkind: \"ack\";\n\trunId: string;\n\tresolution: \"server_ack\";\n}\n\ntype PiServerRunStateRecord = PiServerPendingRunState | PiServerAcknowledgedRunState;\n\ninterface PiServerRunStateEnvelope {\n\tpayload: string;\n\tsha256: string;\n}\n\nexport interface WritePiServerPendingRunInput {\n\tserverHash: string;\n\tsessionId: string;\n\trunId: string;\n\tbaseTreeHash: string;\n\tbaseEntryCount: number;\n\tbaseLeafId: string | null;\n\trequestHash: string;\n\ttimestamp?: number;\n}\n\ninterface ParsedPiServerRunState {\n\tnextSequence: number;\n\tpending: PiServerPendingRunState | undefined;\n}\n\nexport interface PiServerRunStateLease {\n\treadonly path: string;\n\treadonly database: DatabaseSync;\n\tactive: boolean;\n}\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport function acquirePiServerRunStateLease(path: string): PiServerRunStateLease {\n\tconst normalizedPath = resolve(path);\n\tconst database = new DatabaseSync(`${normalizedPath}.lock.sqlite`);\n\tlet transactionStarted = false;\n\ttry {\n\t\tdatabase.exec(\"PRAGMA busy_timeout = 0\");\n\t\tdatabase.exec(\"CREATE TABLE IF NOT EXISTS run_state_lock (id INTEGER PRIMARY KEY CHECK (id = 1))\");\n\t\tdatabase.exec(\"BEGIN IMMEDIATE\");\n\t\ttransactionStarted = true;\n\t\treturn { path: normalizedPath, database, active: true };\n\t} catch (error) {\n\t\tif (transactionStarted) {\n\t\t\ttry {\n\t\t\t\tdatabase.exec(\"ROLLBACK\");\n\t\t\t} catch {\n\t\t\t\t// Closing the connection below is the authoritative lock release.\n\t\t\t}\n\t\t}\n\t\tdatabase.close();\n\t\tthrow new Error(`Cannot acquire pi-server run lease for ${normalizedPath}; another process owns the session`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nexport function releasePiServerRunStateLease(lease: PiServerRunStateLease): void {\n\tif (!lease.active) return;\n\tlease.active = false;\n\ttry {\n\t\tlease.database.exec(\"ROLLBACK\");\n\t} catch {\n\t\t// close() still releases the OS-backed SQLite transaction after connection failure.\n\t}\n\ttry {\n\t\tlease.database.close();\n\t} catch {\n\t\t// The lease is already unusable and close() is idempotent at this abstraction boundary.\n\t}\n}\n\nfunction assertPiServerRunStateLease(path: string, lease: PiServerRunStateLease): void {\n\tif (!lease.active) {\n\t\tthrow new Error(\"Cannot use a released pi-server run lease\");\n\t}\n\tconst normalizedPath = resolve(path);\n\tif (lease.path !== normalizedPath) {\n\t\tthrow new Error(`Pi-server run lease path mismatch: expected ${normalizedPath}, received ${lease.path}`);\n\t}\n}\n\nfunction withRunStateLease<T>(path: string, lease: PiServerRunStateLease | undefined, operation: () => T): T {\n\tif (lease) {\n\t\tassertPiServerRunStateLease(path, lease);\n\t\treturn operation();\n\t}\n\tconst acquiredLease = acquirePiServerRunStateLease(path);\n\ttry {\n\t\treturn operation();\n\t} finally {\n\t\treleasePiServerRunStateLease(acquiredLease);\n\t}\n}\n\nfunction assertObject(value: unknown, path: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${path} must be an object`);\n\t}\n}\n\nfunction assertIdentifier(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > IDENTIFIER_MAX_CHARS) {\n\t\tthrow new Error(`${path} must be a non-empty string up to ${IDENTIFIER_MAX_CHARS} characters`);\n\t}\n}\n\nfunction assertHash(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\" || !SHA256_PATTERN.test(value)) {\n\t\tthrow new Error(`${path} must be a 64-character hex digest`);\n\t}\n}\n\nfunction assertNonNegativeSafeInteger(value: unknown, path: string): asserts value is number {\n\tif (!Number.isSafeInteger(value) || (value as number) < 0) {\n\t\tthrow new Error(`${path} must be a non-negative safe integer`);\n\t}\n}\n\nfunction parseRecord(payload: string, lineNumber: number): PiServerRunStateRecord {\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(payload) as unknown;\n\t} catch (error) {\n\t\tthrow new Error(`pi-server run state payload is invalid JSON at line ${lineNumber}`, { cause: error });\n\t}\n\tassertObject(value, `pi-server run state line ${lineNumber}`);\n\tif (value.version !== RUN_STATE_VERSION) {\n\t\tthrow new Error(`Unsupported pi-server run state version at line ${lineNumber}`);\n\t}\n\tassertNonNegativeSafeInteger(value.sequence, `pi-server run state line ${lineNumber}.sequence`);\n\tassertNonNegativeSafeInteger(value.timestamp, `pi-server run state line ${lineNumber}.timestamp`);\n\tif (value.kind === \"ack\") {\n\t\tassertIdentifier(value.runId, `pi-server run state line ${lineNumber}.runId`);\n\t\tif (value.resolution !== \"server_ack\") {\n\t\t\tthrow new Error(`pi-server run state acknowledgement resolution is invalid at line ${lineNumber}`);\n\t\t}\n\t\treturn {\n\t\t\tversion: RUN_STATE_VERSION,\n\t\t\tkind: \"ack\",\n\t\t\tsequence: value.sequence,\n\t\t\ttimestamp: value.timestamp,\n\t\t\trunId: value.runId,\n\t\t\tresolution: value.resolution,\n\t\t};\n\t}\n\tif (value.kind !== \"run\") {\n\t\tthrow new Error(`Unsupported pi-server run state record kind at line ${lineNumber}`);\n\t}\n\tassertHash(value.serverHash, `pi-server run state line ${lineNumber}.serverHash`);\n\tassertIdentifier(value.sessionId, `pi-server run state line ${lineNumber}.sessionId`);\n\tassertIdentifier(value.runId, `pi-server run state line ${lineNumber}.runId`);\n\tassertHash(value.baseTreeHash, `pi-server run state line ${lineNumber}.baseTreeHash`);\n\tassertNonNegativeSafeInteger(value.baseEntryCount, `pi-server run state line ${lineNumber}.baseEntryCount`);\n\tif (value.baseLeafId !== null) {\n\t\tassertIdentifier(value.baseLeafId, `pi-server run state line ${lineNumber}.baseLeafId`);\n\t}\n\tassertHash(value.requestHash, `pi-server run state line ${lineNumber}.requestHash`);\n\treturn {\n\t\tversion: RUN_STATE_VERSION,\n\t\tkind: \"run\",\n\t\tsequence: value.sequence,\n\t\ttimestamp: value.timestamp,\n\t\tserverHash: value.serverHash,\n\t\tsessionId: value.sessionId,\n\t\trunId: value.runId,\n\t\tbaseTreeHash: value.baseTreeHash,\n\t\tbaseEntryCount: value.baseEntryCount,\n\t\tbaseLeafId: value.baseLeafId,\n\t\trequestHash: value.requestHash,\n\t};\n}\n\nfunction parseRunStateFile(path: string): ParsedPiServerRunState {\n\tif (!existsSync(path)) {\n\t\treturn { nextSequence: 0, pending: undefined };\n\t}\n\tconst encoded = readFileSync(path);\n\tif (encoded.byteLength > RUN_STATE_MAX_BYTES) {\n\t\tthrow new Error(`pi-server run state exceeds ${RUN_STATE_MAX_BYTES} bytes: ${path}`);\n\t}\n\tconst content = encoded.toString(\"utf-8\");\n\tconst hasCompleteTail = content.endsWith(\"\\n\");\n\tconst lines = content.split(\"\\n\");\n\tif (!hasCompleteTail) {\n\t\tlines.pop();\n\t}\n\tlet expectedSequence = 0;\n\tlet pending: PiServerPendingRunState | undefined;\n\tfor (const [index, line] of lines.entries()) {\n\t\tif (line.length === 0) continue;\n\t\tlet envelopeValue: unknown;\n\t\ttry {\n\t\t\tenvelopeValue = JSON.parse(line) as unknown;\n\t\t} catch (error) {\n\t\t\tthrow new Error(`pi-server run state envelope is invalid JSON at line ${index + 1}`, { cause: error });\n\t\t}\n\t\tassertObject(envelopeValue, `pi-server run state envelope line ${index + 1}`);\n\t\tif (typeof envelopeValue.payload !== \"string\") {\n\t\t\tthrow new Error(`pi-server run state envelope payload must be a string at line ${index + 1}`);\n\t\t}\n\t\tassertHash(envelopeValue.sha256, `pi-server run state envelope line ${index + 1}.sha256`);\n\t\tif (sha256(envelopeValue.payload) !== envelopeValue.sha256) {\n\t\t\tthrow new Error(`pi-server run state checksum mismatch at line ${index + 1}`);\n\t\t}\n\t\tconst record = parseRecord(envelopeValue.payload, index + 1);\n\t\tif (record.sequence !== expectedSequence) {\n\t\t\tthrow new Error(\n\t\t\t\t`pi-server run state sequence mismatch at line ${index + 1}: expected ${expectedSequence}, received ${record.sequence}`,\n\t\t\t);\n\t\t}\n\t\texpectedSequence++;\n\t\tif (record.kind === \"run\") {\n\t\t\tif (pending) {\n\t\t\t\tthrow new Error(`pi-server run state contains a new run before ${pending.runId} was acknowledged`);\n\t\t\t}\n\t\t\tpending = record;\n\t\t} else {\n\t\t\tif (!pending || pending.runId !== record.runId) {\n\t\t\t\tthrow new Error(`pi-server run state acknowledgement does not match the pending run at line ${index + 1}`);\n\t\t\t}\n\t\t\tpending = undefined;\n\t\t}\n\t}\n\treturn { nextSequence: expectedSequence, pending };\n}\n\nfunction appendRecord(path: string, record: PiServerRunStateRecord): void {\n\tconst payload = JSON.stringify(record);\n\tconst envelope: PiServerRunStateEnvelope = { payload, sha256: sha256(payload) };\n\tconst encoded = Buffer.from(`${JSON.stringify(envelope)}\\n`, \"utf-8\");\n\tconst existing = existsSync(path) ? readFileSync(path) : Buffer.alloc(0);\n\tconst validBytes = existing.lastIndexOf(0x0a) + 1;\n\tif (validBytes !== existing.byteLength) {\n\t\ttruncateSync(path, validBytes);\n\t}\n\tconst existingBytes = validBytes;\n\tif (existingBytes + encoded.byteLength > RUN_STATE_MAX_BYTES) {\n\t\tthrow new Error(`pi-server run state would exceed ${RUN_STATE_MAX_BYTES} bytes: ${path}`);\n\t}\n\tconst fileExisted = existsSync(path);\n\tconst handle = openSync(path, \"a\", 0o600);\n\ttry {\n\t\tlet written = 0;\n\t\twhile (written < encoded.byteLength) {\n\t\t\tconst bytesWritten = writeSync(handle, encoded, written, encoded.byteLength - written);\n\t\t\tif (bytesWritten === 0) {\n\t\t\t\tthrow new Error(`Failed to make progress writing pi-server run state: ${path}`);\n\t\t\t}\n\t\t\twritten += bytesWritten;\n\t\t}\n\t\tfsyncSync(handle);\n\t} finally {\n\t\tcloseSync(handle);\n\t}\n\tif (!fileExisted && process.platform !== \"win32\") {\n\t\tconst directoryHandle = openSync(dirname(path), \"r\");\n\t\ttry {\n\t\t\tfsyncSync(directoryHandle);\n\t\t} finally {\n\t\t\tcloseSync(directoryHandle);\n\t\t}\n\t}\n}\n\nexport function getPiServerRunStatePath(sessionFile: string): string {\n\treturn `${sessionFile}.pi-server-runs.jsonl`;\n}\n\nexport function hashPiServerIdentity(serverUrl: string): string {\n\treturn sha256(serverUrl);\n}\n\nexport function readPiServerPendingRun(\n\tpath: string,\n\tlease?: PiServerRunStateLease,\n): PiServerPendingRunState | undefined {\n\tif (lease) {\n\t\tassertPiServerRunStateLease(path, lease);\n\t}\n\t// The append-only checksum envelope makes an unlocked observer read safe: a concurrent\n\t// incomplete final record is ignored. Lifecycle decisions pass the owning lease.\n\treturn parseRunStateFile(path).pending;\n}\n\nexport function writePiServerPendingRun(\n\tpath: string,\n\tinput: WritePiServerPendingRunInput,\n\tlease?: PiServerRunStateLease,\n): PiServerPendingRunState {\n\treturn withRunStateLease(path, lease, () => {\n\t\tconst state = parseRunStateFile(path);\n\t\tif (state.pending) {\n\t\t\tthrow new Error(`pi-server run ${state.pending.runId} must be acknowledged before starting another run`);\n\t\t}\n\t\tif (state.nextSequence > 0) {\n\t\t\t// All earlier runs are acknowledged. Truncating before the new durable marker is safe:\n\t\t\t// the caller cannot submit the new provider request until this function returns.\n\t\t\ttruncateSync(path, 0);\n\t\t\tstate.nextSequence = 0;\n\t\t}\n\t\tconst timestamp = input.timestamp ?? Date.now();\n\t\tassertNonNegativeSafeInteger(timestamp, \"pi-server run state timestamp\");\n\t\tassertHash(input.serverHash, \"pi-server run state serverHash\");\n\t\tassertIdentifier(input.sessionId, \"pi-server run state sessionId\");\n\t\tassertIdentifier(input.runId, \"pi-server run state runId\");\n\t\tassertHash(input.baseTreeHash, \"pi-server run state baseTreeHash\");\n\t\tassertNonNegativeSafeInteger(input.baseEntryCount, \"pi-server run state baseEntryCount\");\n\t\tif (input.baseLeafId !== null) {\n\t\t\tassertIdentifier(input.baseLeafId, \"pi-server run state baseLeafId\");\n\t\t}\n\t\tassertHash(input.requestHash, \"pi-server run state requestHash\");\n\t\tconst record: PiServerPendingRunState = {\n\t\t\tversion: RUN_STATE_VERSION,\n\t\t\tkind: \"run\",\n\t\t\tsequence: state.nextSequence,\n\t\t\ttimestamp,\n\t\t\tserverHash: input.serverHash,\n\t\t\tsessionId: input.sessionId,\n\t\t\trunId: input.runId,\n\t\t\tbaseTreeHash: input.baseTreeHash,\n\t\t\tbaseEntryCount: input.baseEntryCount,\n\t\t\tbaseLeafId: input.baseLeafId,\n\t\t\trequestHash: input.requestHash,\n\t\t};\n\t\tappendRecord(path, record);\n\t\treturn record;\n\t});\n}\n\nexport function acknowledgePiServerPendingRun(\n\tpath: string,\n\trunId: string,\n\ttimestamp = Date.now(),\n\tlease?: PiServerRunStateLease,\n): void {\n\twithRunStateLease(path, lease, () => {\n\t\tconst state = parseRunStateFile(path);\n\t\tif (!state.pending) return;\n\t\tif (state.pending.runId !== runId) {\n\t\t\tthrow new Error(`Cannot acknowledge pi-server run ${runId}; pending run is ${state.pending.runId}`);\n\t\t}\n\t\tassertNonNegativeSafeInteger(timestamp, \"pi-server run acknowledgement timestamp\");\n\t\tappendRecord(path, {\n\t\t\tversion: RUN_STATE_VERSION,\n\t\t\tkind: \"ack\",\n\t\t\tsequence: state.nextSequence,\n\t\t\ttimestamp,\n\t\t\trunId,\n\t\t\tresolution: \"server_ack\",\n\t\t});\n\t});\n}\n"]}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { closeSync, existsSync, fsyncSync, openSync, readFileSync, truncateSync, writeSync } from "node:fs";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { DatabaseSync } from "node:sqlite";
|
|
6
|
+
const RUN_STATE_VERSION = 1;
|
|
7
|
+
const RUN_STATE_MAX_BYTES = 8 * 1024 * 1024;
|
|
8
|
+
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
9
|
+
const IDENTIFIER_MAX_CHARS = 1024;
|
|
10
|
+
function sha256(value) {
|
|
11
|
+
return createHash("sha256").update(value).digest("hex");
|
|
12
|
+
}
|
|
13
|
+
export function acquirePiServerRunStateLease(path) {
|
|
14
|
+
const normalizedPath = resolve(path);
|
|
15
|
+
const database = new DatabaseSync(`${normalizedPath}.lock.sqlite`);
|
|
16
|
+
let transactionStarted = false;
|
|
17
|
+
try {
|
|
18
|
+
database.exec("PRAGMA busy_timeout = 0");
|
|
19
|
+
database.exec("CREATE TABLE IF NOT EXISTS run_state_lock (id INTEGER PRIMARY KEY CHECK (id = 1))");
|
|
20
|
+
database.exec("BEGIN IMMEDIATE");
|
|
21
|
+
transactionStarted = true;
|
|
22
|
+
return { path: normalizedPath, database, active: true };
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (transactionStarted) {
|
|
26
|
+
try {
|
|
27
|
+
database.exec("ROLLBACK");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Closing the connection below is the authoritative lock release.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
database.close();
|
|
34
|
+
throw new Error(`Cannot acquire pi-server run lease for ${normalizedPath}; another process owns the session`, {
|
|
35
|
+
cause: error,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function releasePiServerRunStateLease(lease) {
|
|
40
|
+
if (!lease.active)
|
|
41
|
+
return;
|
|
42
|
+
lease.active = false;
|
|
43
|
+
try {
|
|
44
|
+
lease.database.exec("ROLLBACK");
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// close() still releases the OS-backed SQLite transaction after connection failure.
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
lease.database.close();
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// The lease is already unusable and close() is idempotent at this abstraction boundary.
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function assertPiServerRunStateLease(path, lease) {
|
|
57
|
+
if (!lease.active) {
|
|
58
|
+
throw new Error("Cannot use a released pi-server run lease");
|
|
59
|
+
}
|
|
60
|
+
const normalizedPath = resolve(path);
|
|
61
|
+
if (lease.path !== normalizedPath) {
|
|
62
|
+
throw new Error(`Pi-server run lease path mismatch: expected ${normalizedPath}, received ${lease.path}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function withRunStateLease(path, lease, operation) {
|
|
66
|
+
if (lease) {
|
|
67
|
+
assertPiServerRunStateLease(path, lease);
|
|
68
|
+
return operation();
|
|
69
|
+
}
|
|
70
|
+
const acquiredLease = acquirePiServerRunStateLease(path);
|
|
71
|
+
try {
|
|
72
|
+
return operation();
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
releasePiServerRunStateLease(acquiredLease);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function assertObject(value, path) {
|
|
79
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
80
|
+
throw new Error(`${path} must be an object`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function assertIdentifier(value, path) {
|
|
84
|
+
if (typeof value !== "string" || value.length === 0 || value.length > IDENTIFIER_MAX_CHARS) {
|
|
85
|
+
throw new Error(`${path} must be a non-empty string up to ${IDENTIFIER_MAX_CHARS} characters`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function assertHash(value, path) {
|
|
89
|
+
if (typeof value !== "string" || !SHA256_PATTERN.test(value)) {
|
|
90
|
+
throw new Error(`${path} must be a 64-character hex digest`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function assertNonNegativeSafeInteger(value, path) {
|
|
94
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
95
|
+
throw new Error(`${path} must be a non-negative safe integer`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function parseRecord(payload, lineNumber) {
|
|
99
|
+
let value;
|
|
100
|
+
try {
|
|
101
|
+
value = JSON.parse(payload);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
throw new Error(`pi-server run state payload is invalid JSON at line ${lineNumber}`, { cause: error });
|
|
105
|
+
}
|
|
106
|
+
assertObject(value, `pi-server run state line ${lineNumber}`);
|
|
107
|
+
if (value.version !== RUN_STATE_VERSION) {
|
|
108
|
+
throw new Error(`Unsupported pi-server run state version at line ${lineNumber}`);
|
|
109
|
+
}
|
|
110
|
+
assertNonNegativeSafeInteger(value.sequence, `pi-server run state line ${lineNumber}.sequence`);
|
|
111
|
+
assertNonNegativeSafeInteger(value.timestamp, `pi-server run state line ${lineNumber}.timestamp`);
|
|
112
|
+
if (value.kind === "ack") {
|
|
113
|
+
assertIdentifier(value.runId, `pi-server run state line ${lineNumber}.runId`);
|
|
114
|
+
if (value.resolution !== "server_ack") {
|
|
115
|
+
throw new Error(`pi-server run state acknowledgement resolution is invalid at line ${lineNumber}`);
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
version: RUN_STATE_VERSION,
|
|
119
|
+
kind: "ack",
|
|
120
|
+
sequence: value.sequence,
|
|
121
|
+
timestamp: value.timestamp,
|
|
122
|
+
runId: value.runId,
|
|
123
|
+
resolution: value.resolution,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (value.kind !== "run") {
|
|
127
|
+
throw new Error(`Unsupported pi-server run state record kind at line ${lineNumber}`);
|
|
128
|
+
}
|
|
129
|
+
assertHash(value.serverHash, `pi-server run state line ${lineNumber}.serverHash`);
|
|
130
|
+
assertIdentifier(value.sessionId, `pi-server run state line ${lineNumber}.sessionId`);
|
|
131
|
+
assertIdentifier(value.runId, `pi-server run state line ${lineNumber}.runId`);
|
|
132
|
+
assertHash(value.baseTreeHash, `pi-server run state line ${lineNumber}.baseTreeHash`);
|
|
133
|
+
assertNonNegativeSafeInteger(value.baseEntryCount, `pi-server run state line ${lineNumber}.baseEntryCount`);
|
|
134
|
+
if (value.baseLeafId !== null) {
|
|
135
|
+
assertIdentifier(value.baseLeafId, `pi-server run state line ${lineNumber}.baseLeafId`);
|
|
136
|
+
}
|
|
137
|
+
assertHash(value.requestHash, `pi-server run state line ${lineNumber}.requestHash`);
|
|
138
|
+
return {
|
|
139
|
+
version: RUN_STATE_VERSION,
|
|
140
|
+
kind: "run",
|
|
141
|
+
sequence: value.sequence,
|
|
142
|
+
timestamp: value.timestamp,
|
|
143
|
+
serverHash: value.serverHash,
|
|
144
|
+
sessionId: value.sessionId,
|
|
145
|
+
runId: value.runId,
|
|
146
|
+
baseTreeHash: value.baseTreeHash,
|
|
147
|
+
baseEntryCount: value.baseEntryCount,
|
|
148
|
+
baseLeafId: value.baseLeafId,
|
|
149
|
+
requestHash: value.requestHash,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function parseRunStateFile(path) {
|
|
153
|
+
if (!existsSync(path)) {
|
|
154
|
+
return { nextSequence: 0, pending: undefined };
|
|
155
|
+
}
|
|
156
|
+
const encoded = readFileSync(path);
|
|
157
|
+
if (encoded.byteLength > RUN_STATE_MAX_BYTES) {
|
|
158
|
+
throw new Error(`pi-server run state exceeds ${RUN_STATE_MAX_BYTES} bytes: ${path}`);
|
|
159
|
+
}
|
|
160
|
+
const content = encoded.toString("utf-8");
|
|
161
|
+
const hasCompleteTail = content.endsWith("\n");
|
|
162
|
+
const lines = content.split("\n");
|
|
163
|
+
if (!hasCompleteTail) {
|
|
164
|
+
lines.pop();
|
|
165
|
+
}
|
|
166
|
+
let expectedSequence = 0;
|
|
167
|
+
let pending;
|
|
168
|
+
for (const [index, line] of lines.entries()) {
|
|
169
|
+
if (line.length === 0)
|
|
170
|
+
continue;
|
|
171
|
+
let envelopeValue;
|
|
172
|
+
try {
|
|
173
|
+
envelopeValue = JSON.parse(line);
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
throw new Error(`pi-server run state envelope is invalid JSON at line ${index + 1}`, { cause: error });
|
|
177
|
+
}
|
|
178
|
+
assertObject(envelopeValue, `pi-server run state envelope line ${index + 1}`);
|
|
179
|
+
if (typeof envelopeValue.payload !== "string") {
|
|
180
|
+
throw new Error(`pi-server run state envelope payload must be a string at line ${index + 1}`);
|
|
181
|
+
}
|
|
182
|
+
assertHash(envelopeValue.sha256, `pi-server run state envelope line ${index + 1}.sha256`);
|
|
183
|
+
if (sha256(envelopeValue.payload) !== envelopeValue.sha256) {
|
|
184
|
+
throw new Error(`pi-server run state checksum mismatch at line ${index + 1}`);
|
|
185
|
+
}
|
|
186
|
+
const record = parseRecord(envelopeValue.payload, index + 1);
|
|
187
|
+
if (record.sequence !== expectedSequence) {
|
|
188
|
+
throw new Error(`pi-server run state sequence mismatch at line ${index + 1}: expected ${expectedSequence}, received ${record.sequence}`);
|
|
189
|
+
}
|
|
190
|
+
expectedSequence++;
|
|
191
|
+
if (record.kind === "run") {
|
|
192
|
+
if (pending) {
|
|
193
|
+
throw new Error(`pi-server run state contains a new run before ${pending.runId} was acknowledged`);
|
|
194
|
+
}
|
|
195
|
+
pending = record;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
if (!pending || pending.runId !== record.runId) {
|
|
199
|
+
throw new Error(`pi-server run state acknowledgement does not match the pending run at line ${index + 1}`);
|
|
200
|
+
}
|
|
201
|
+
pending = undefined;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return { nextSequence: expectedSequence, pending };
|
|
205
|
+
}
|
|
206
|
+
function appendRecord(path, record) {
|
|
207
|
+
const payload = JSON.stringify(record);
|
|
208
|
+
const envelope = { payload, sha256: sha256(payload) };
|
|
209
|
+
const encoded = Buffer.from(`${JSON.stringify(envelope)}\n`, "utf-8");
|
|
210
|
+
const existing = existsSync(path) ? readFileSync(path) : Buffer.alloc(0);
|
|
211
|
+
const validBytes = existing.lastIndexOf(0x0a) + 1;
|
|
212
|
+
if (validBytes !== existing.byteLength) {
|
|
213
|
+
truncateSync(path, validBytes);
|
|
214
|
+
}
|
|
215
|
+
const existingBytes = validBytes;
|
|
216
|
+
if (existingBytes + encoded.byteLength > RUN_STATE_MAX_BYTES) {
|
|
217
|
+
throw new Error(`pi-server run state would exceed ${RUN_STATE_MAX_BYTES} bytes: ${path}`);
|
|
218
|
+
}
|
|
219
|
+
const fileExisted = existsSync(path);
|
|
220
|
+
const handle = openSync(path, "a", 0o600);
|
|
221
|
+
try {
|
|
222
|
+
let written = 0;
|
|
223
|
+
while (written < encoded.byteLength) {
|
|
224
|
+
const bytesWritten = writeSync(handle, encoded, written, encoded.byteLength - written);
|
|
225
|
+
if (bytesWritten === 0) {
|
|
226
|
+
throw new Error(`Failed to make progress writing pi-server run state: ${path}`);
|
|
227
|
+
}
|
|
228
|
+
written += bytesWritten;
|
|
229
|
+
}
|
|
230
|
+
fsyncSync(handle);
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
closeSync(handle);
|
|
234
|
+
}
|
|
235
|
+
if (!fileExisted && process.platform !== "win32") {
|
|
236
|
+
const directoryHandle = openSync(dirname(path), "r");
|
|
237
|
+
try {
|
|
238
|
+
fsyncSync(directoryHandle);
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
closeSync(directoryHandle);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export function getPiServerRunStatePath(sessionFile) {
|
|
246
|
+
return `${sessionFile}.pi-server-runs.jsonl`;
|
|
247
|
+
}
|
|
248
|
+
export function hashPiServerIdentity(serverUrl) {
|
|
249
|
+
return sha256(serverUrl);
|
|
250
|
+
}
|
|
251
|
+
export function readPiServerPendingRun(path, lease) {
|
|
252
|
+
if (lease) {
|
|
253
|
+
assertPiServerRunStateLease(path, lease);
|
|
254
|
+
}
|
|
255
|
+
// The append-only checksum envelope makes an unlocked observer read safe: a concurrent
|
|
256
|
+
// incomplete final record is ignored. Lifecycle decisions pass the owning lease.
|
|
257
|
+
return parseRunStateFile(path).pending;
|
|
258
|
+
}
|
|
259
|
+
export function writePiServerPendingRun(path, input, lease) {
|
|
260
|
+
return withRunStateLease(path, lease, () => {
|
|
261
|
+
const state = parseRunStateFile(path);
|
|
262
|
+
if (state.pending) {
|
|
263
|
+
throw new Error(`pi-server run ${state.pending.runId} must be acknowledged before starting another run`);
|
|
264
|
+
}
|
|
265
|
+
if (state.nextSequence > 0) {
|
|
266
|
+
// All earlier runs are acknowledged. Truncating before the new durable marker is safe:
|
|
267
|
+
// the caller cannot submit the new provider request until this function returns.
|
|
268
|
+
truncateSync(path, 0);
|
|
269
|
+
state.nextSequence = 0;
|
|
270
|
+
}
|
|
271
|
+
const timestamp = input.timestamp ?? Date.now();
|
|
272
|
+
assertNonNegativeSafeInteger(timestamp, "pi-server run state timestamp");
|
|
273
|
+
assertHash(input.serverHash, "pi-server run state serverHash");
|
|
274
|
+
assertIdentifier(input.sessionId, "pi-server run state sessionId");
|
|
275
|
+
assertIdentifier(input.runId, "pi-server run state runId");
|
|
276
|
+
assertHash(input.baseTreeHash, "pi-server run state baseTreeHash");
|
|
277
|
+
assertNonNegativeSafeInteger(input.baseEntryCount, "pi-server run state baseEntryCount");
|
|
278
|
+
if (input.baseLeafId !== null) {
|
|
279
|
+
assertIdentifier(input.baseLeafId, "pi-server run state baseLeafId");
|
|
280
|
+
}
|
|
281
|
+
assertHash(input.requestHash, "pi-server run state requestHash");
|
|
282
|
+
const record = {
|
|
283
|
+
version: RUN_STATE_VERSION,
|
|
284
|
+
kind: "run",
|
|
285
|
+
sequence: state.nextSequence,
|
|
286
|
+
timestamp,
|
|
287
|
+
serverHash: input.serverHash,
|
|
288
|
+
sessionId: input.sessionId,
|
|
289
|
+
runId: input.runId,
|
|
290
|
+
baseTreeHash: input.baseTreeHash,
|
|
291
|
+
baseEntryCount: input.baseEntryCount,
|
|
292
|
+
baseLeafId: input.baseLeafId,
|
|
293
|
+
requestHash: input.requestHash,
|
|
294
|
+
};
|
|
295
|
+
appendRecord(path, record);
|
|
296
|
+
return record;
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
export function acknowledgePiServerPendingRun(path, runId, timestamp = Date.now(), lease) {
|
|
300
|
+
withRunStateLease(path, lease, () => {
|
|
301
|
+
const state = parseRunStateFile(path);
|
|
302
|
+
if (!state.pending)
|
|
303
|
+
return;
|
|
304
|
+
if (state.pending.runId !== runId) {
|
|
305
|
+
throw new Error(`Cannot acknowledge pi-server run ${runId}; pending run is ${state.pending.runId}`);
|
|
306
|
+
}
|
|
307
|
+
assertNonNegativeSafeInteger(timestamp, "pi-server run acknowledgement timestamp");
|
|
308
|
+
appendRecord(path, {
|
|
309
|
+
version: RUN_STATE_VERSION,
|
|
310
|
+
kind: "ack",
|
|
311
|
+
sequence: state.nextSequence,
|
|
312
|
+
timestamp,
|
|
313
|
+
runId,
|
|
314
|
+
resolution: "server_ack",
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=pi-server-run-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-server-run-state.js","sourceRoot":"","sources":["../../src/core/pi-server-run-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { createHash } from \"node:crypto\";\nimport { closeSync, existsSync, fsyncSync, openSync, readFileSync, truncateSync, writeSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\n\nconst RUN_STATE_VERSION = 1;\nconst RUN_STATE_MAX_BYTES = 8 * 1024 * 1024;\nconst SHA256_PATTERN = /^[a-f0-9]{64}$/;\nconst IDENTIFIER_MAX_CHARS = 1024;\n\ninterface PiServerRunStateBase {\n\tversion: typeof RUN_STATE_VERSION;\n\tsequence: number;\n\ttimestamp: number;\n}\n\nexport interface PiServerPendingRunState extends PiServerRunStateBase {\n\tkind: \"run\";\n\tserverHash: string;\n\tsessionId: string;\n\trunId: string;\n\tbaseTreeHash: string;\n\tbaseEntryCount: number;\n\tbaseLeafId: string | null;\n\trequestHash: string;\n}\n\ninterface PiServerAcknowledgedRunState extends PiServerRunStateBase {\n\tkind: \"ack\";\n\trunId: string;\n\tresolution: \"server_ack\";\n}\n\ntype PiServerRunStateRecord = PiServerPendingRunState | PiServerAcknowledgedRunState;\n\ninterface PiServerRunStateEnvelope {\n\tpayload: string;\n\tsha256: string;\n}\n\nexport interface WritePiServerPendingRunInput {\n\tserverHash: string;\n\tsessionId: string;\n\trunId: string;\n\tbaseTreeHash: string;\n\tbaseEntryCount: number;\n\tbaseLeafId: string | null;\n\trequestHash: string;\n\ttimestamp?: number;\n}\n\ninterface ParsedPiServerRunState {\n\tnextSequence: number;\n\tpending: PiServerPendingRunState | undefined;\n}\n\nexport interface PiServerRunStateLease {\n\treadonly path: string;\n\treadonly database: DatabaseSync;\n\tactive: boolean;\n}\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport function acquirePiServerRunStateLease(path: string): PiServerRunStateLease {\n\tconst normalizedPath = resolve(path);\n\tconst database = new DatabaseSync(`${normalizedPath}.lock.sqlite`);\n\tlet transactionStarted = false;\n\ttry {\n\t\tdatabase.exec(\"PRAGMA busy_timeout = 0\");\n\t\tdatabase.exec(\"CREATE TABLE IF NOT EXISTS run_state_lock (id INTEGER PRIMARY KEY CHECK (id = 1))\");\n\t\tdatabase.exec(\"BEGIN IMMEDIATE\");\n\t\ttransactionStarted = true;\n\t\treturn { path: normalizedPath, database, active: true };\n\t} catch (error) {\n\t\tif (transactionStarted) {\n\t\t\ttry {\n\t\t\t\tdatabase.exec(\"ROLLBACK\");\n\t\t\t} catch {\n\t\t\t\t// Closing the connection below is the authoritative lock release.\n\t\t\t}\n\t\t}\n\t\tdatabase.close();\n\t\tthrow new Error(`Cannot acquire pi-server run lease for ${normalizedPath}; another process owns the session`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nexport function releasePiServerRunStateLease(lease: PiServerRunStateLease): void {\n\tif (!lease.active) return;\n\tlease.active = false;\n\ttry {\n\t\tlease.database.exec(\"ROLLBACK\");\n\t} catch {\n\t\t// close() still releases the OS-backed SQLite transaction after connection failure.\n\t}\n\ttry {\n\t\tlease.database.close();\n\t} catch {\n\t\t// The lease is already unusable and close() is idempotent at this abstraction boundary.\n\t}\n}\n\nfunction assertPiServerRunStateLease(path: string, lease: PiServerRunStateLease): void {\n\tif (!lease.active) {\n\t\tthrow new Error(\"Cannot use a released pi-server run lease\");\n\t}\n\tconst normalizedPath = resolve(path);\n\tif (lease.path !== normalizedPath) {\n\t\tthrow new Error(`Pi-server run lease path mismatch: expected ${normalizedPath}, received ${lease.path}`);\n\t}\n}\n\nfunction withRunStateLease<T>(path: string, lease: PiServerRunStateLease | undefined, operation: () => T): T {\n\tif (lease) {\n\t\tassertPiServerRunStateLease(path, lease);\n\t\treturn operation();\n\t}\n\tconst acquiredLease = acquirePiServerRunStateLease(path);\n\ttry {\n\t\treturn operation();\n\t} finally {\n\t\treleasePiServerRunStateLease(acquiredLease);\n\t}\n}\n\nfunction assertObject(value: unknown, path: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${path} must be an object`);\n\t}\n}\n\nfunction assertIdentifier(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > IDENTIFIER_MAX_CHARS) {\n\t\tthrow new Error(`${path} must be a non-empty string up to ${IDENTIFIER_MAX_CHARS} characters`);\n\t}\n}\n\nfunction assertHash(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\" || !SHA256_PATTERN.test(value)) {\n\t\tthrow new Error(`${path} must be a 64-character hex digest`);\n\t}\n}\n\nfunction assertNonNegativeSafeInteger(value: unknown, path: string): asserts value is number {\n\tif (!Number.isSafeInteger(value) || (value as number) < 0) {\n\t\tthrow new Error(`${path} must be a non-negative safe integer`);\n\t}\n}\n\nfunction parseRecord(payload: string, lineNumber: number): PiServerRunStateRecord {\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(payload) as unknown;\n\t} catch (error) {\n\t\tthrow new Error(`pi-server run state payload is invalid JSON at line ${lineNumber}`, { cause: error });\n\t}\n\tassertObject(value, `pi-server run state line ${lineNumber}`);\n\tif (value.version !== RUN_STATE_VERSION) {\n\t\tthrow new Error(`Unsupported pi-server run state version at line ${lineNumber}`);\n\t}\n\tassertNonNegativeSafeInteger(value.sequence, `pi-server run state line ${lineNumber}.sequence`);\n\tassertNonNegativeSafeInteger(value.timestamp, `pi-server run state line ${lineNumber}.timestamp`);\n\tif (value.kind === \"ack\") {\n\t\tassertIdentifier(value.runId, `pi-server run state line ${lineNumber}.runId`);\n\t\tif (value.resolution !== \"server_ack\") {\n\t\t\tthrow new Error(`pi-server run state acknowledgement resolution is invalid at line ${lineNumber}`);\n\t\t}\n\t\treturn {\n\t\t\tversion: RUN_STATE_VERSION,\n\t\t\tkind: \"ack\",\n\t\t\tsequence: value.sequence,\n\t\t\ttimestamp: value.timestamp,\n\t\t\trunId: value.runId,\n\t\t\tresolution: value.resolution,\n\t\t};\n\t}\n\tif (value.kind !== \"run\") {\n\t\tthrow new Error(`Unsupported pi-server run state record kind at line ${lineNumber}`);\n\t}\n\tassertHash(value.serverHash, `pi-server run state line ${lineNumber}.serverHash`);\n\tassertIdentifier(value.sessionId, `pi-server run state line ${lineNumber}.sessionId`);\n\tassertIdentifier(value.runId, `pi-server run state line ${lineNumber}.runId`);\n\tassertHash(value.baseTreeHash, `pi-server run state line ${lineNumber}.baseTreeHash`);\n\tassertNonNegativeSafeInteger(value.baseEntryCount, `pi-server run state line ${lineNumber}.baseEntryCount`);\n\tif (value.baseLeafId !== null) {\n\t\tassertIdentifier(value.baseLeafId, `pi-server run state line ${lineNumber}.baseLeafId`);\n\t}\n\tassertHash(value.requestHash, `pi-server run state line ${lineNumber}.requestHash`);\n\treturn {\n\t\tversion: RUN_STATE_VERSION,\n\t\tkind: \"run\",\n\t\tsequence: value.sequence,\n\t\ttimestamp: value.timestamp,\n\t\tserverHash: value.serverHash,\n\t\tsessionId: value.sessionId,\n\t\trunId: value.runId,\n\t\tbaseTreeHash: value.baseTreeHash,\n\t\tbaseEntryCount: value.baseEntryCount,\n\t\tbaseLeafId: value.baseLeafId,\n\t\trequestHash: value.requestHash,\n\t};\n}\n\nfunction parseRunStateFile(path: string): ParsedPiServerRunState {\n\tif (!existsSync(path)) {\n\t\treturn { nextSequence: 0, pending: undefined };\n\t}\n\tconst encoded = readFileSync(path);\n\tif (encoded.byteLength > RUN_STATE_MAX_BYTES) {\n\t\tthrow new Error(`pi-server run state exceeds ${RUN_STATE_MAX_BYTES} bytes: ${path}`);\n\t}\n\tconst content = encoded.toString(\"utf-8\");\n\tconst hasCompleteTail = content.endsWith(\"\\n\");\n\tconst lines = content.split(\"\\n\");\n\tif (!hasCompleteTail) {\n\t\tlines.pop();\n\t}\n\tlet expectedSequence = 0;\n\tlet pending: PiServerPendingRunState | undefined;\n\tfor (const [index, line] of lines.entries()) {\n\t\tif (line.length === 0) continue;\n\t\tlet envelopeValue: unknown;\n\t\ttry {\n\t\t\tenvelopeValue = JSON.parse(line) as unknown;\n\t\t} catch (error) {\n\t\t\tthrow new Error(`pi-server run state envelope is invalid JSON at line ${index + 1}`, { cause: error });\n\t\t}\n\t\tassertObject(envelopeValue, `pi-server run state envelope line ${index + 1}`);\n\t\tif (typeof envelopeValue.payload !== \"string\") {\n\t\t\tthrow new Error(`pi-server run state envelope payload must be a string at line ${index + 1}`);\n\t\t}\n\t\tassertHash(envelopeValue.sha256, `pi-server run state envelope line ${index + 1}.sha256`);\n\t\tif (sha256(envelopeValue.payload) !== envelopeValue.sha256) {\n\t\t\tthrow new Error(`pi-server run state checksum mismatch at line ${index + 1}`);\n\t\t}\n\t\tconst record = parseRecord(envelopeValue.payload, index + 1);\n\t\tif (record.sequence !== expectedSequence) {\n\t\t\tthrow new Error(\n\t\t\t\t`pi-server run state sequence mismatch at line ${index + 1}: expected ${expectedSequence}, received ${record.sequence}`,\n\t\t\t);\n\t\t}\n\t\texpectedSequence++;\n\t\tif (record.kind === \"run\") {\n\t\t\tif (pending) {\n\t\t\t\tthrow new Error(`pi-server run state contains a new run before ${pending.runId} was acknowledged`);\n\t\t\t}\n\t\t\tpending = record;\n\t\t} else {\n\t\t\tif (!pending || pending.runId !== record.runId) {\n\t\t\t\tthrow new Error(`pi-server run state acknowledgement does not match the pending run at line ${index + 1}`);\n\t\t\t}\n\t\t\tpending = undefined;\n\t\t}\n\t}\n\treturn { nextSequence: expectedSequence, pending };\n}\n\nfunction appendRecord(path: string, record: PiServerRunStateRecord): void {\n\tconst payload = JSON.stringify(record);\n\tconst envelope: PiServerRunStateEnvelope = { payload, sha256: sha256(payload) };\n\tconst encoded = Buffer.from(`${JSON.stringify(envelope)}\\n`, \"utf-8\");\n\tconst existing = existsSync(path) ? readFileSync(path) : Buffer.alloc(0);\n\tconst validBytes = existing.lastIndexOf(0x0a) + 1;\n\tif (validBytes !== existing.byteLength) {\n\t\ttruncateSync(path, validBytes);\n\t}\n\tconst existingBytes = validBytes;\n\tif (existingBytes + encoded.byteLength > RUN_STATE_MAX_BYTES) {\n\t\tthrow new Error(`pi-server run state would exceed ${RUN_STATE_MAX_BYTES} bytes: ${path}`);\n\t}\n\tconst fileExisted = existsSync(path);\n\tconst handle = openSync(path, \"a\", 0o600);\n\ttry {\n\t\tlet written = 0;\n\t\twhile (written < encoded.byteLength) {\n\t\t\tconst bytesWritten = writeSync(handle, encoded, written, encoded.byteLength - written);\n\t\t\tif (bytesWritten === 0) {\n\t\t\t\tthrow new Error(`Failed to make progress writing pi-server run state: ${path}`);\n\t\t\t}\n\t\t\twritten += bytesWritten;\n\t\t}\n\t\tfsyncSync(handle);\n\t} finally {\n\t\tcloseSync(handle);\n\t}\n\tif (!fileExisted && process.platform !== \"win32\") {\n\t\tconst directoryHandle = openSync(dirname(path), \"r\");\n\t\ttry {\n\t\t\tfsyncSync(directoryHandle);\n\t\t} finally {\n\t\t\tcloseSync(directoryHandle);\n\t\t}\n\t}\n}\n\nexport function getPiServerRunStatePath(sessionFile: string): string {\n\treturn `${sessionFile}.pi-server-runs.jsonl`;\n}\n\nexport function hashPiServerIdentity(serverUrl: string): string {\n\treturn sha256(serverUrl);\n}\n\nexport function readPiServerPendingRun(\n\tpath: string,\n\tlease?: PiServerRunStateLease,\n): PiServerPendingRunState | undefined {\n\tif (lease) {\n\t\tassertPiServerRunStateLease(path, lease);\n\t}\n\t// The append-only checksum envelope makes an unlocked observer read safe: a concurrent\n\t// incomplete final record is ignored. Lifecycle decisions pass the owning lease.\n\treturn parseRunStateFile(path).pending;\n}\n\nexport function writePiServerPendingRun(\n\tpath: string,\n\tinput: WritePiServerPendingRunInput,\n\tlease?: PiServerRunStateLease,\n): PiServerPendingRunState {\n\treturn withRunStateLease(path, lease, () => {\n\t\tconst state = parseRunStateFile(path);\n\t\tif (state.pending) {\n\t\t\tthrow new Error(`pi-server run ${state.pending.runId} must be acknowledged before starting another run`);\n\t\t}\n\t\tif (state.nextSequence > 0) {\n\t\t\t// All earlier runs are acknowledged. Truncating before the new durable marker is safe:\n\t\t\t// the caller cannot submit the new provider request until this function returns.\n\t\t\ttruncateSync(path, 0);\n\t\t\tstate.nextSequence = 0;\n\t\t}\n\t\tconst timestamp = input.timestamp ?? Date.now();\n\t\tassertNonNegativeSafeInteger(timestamp, \"pi-server run state timestamp\");\n\t\tassertHash(input.serverHash, \"pi-server run state serverHash\");\n\t\tassertIdentifier(input.sessionId, \"pi-server run state sessionId\");\n\t\tassertIdentifier(input.runId, \"pi-server run state runId\");\n\t\tassertHash(input.baseTreeHash, \"pi-server run state baseTreeHash\");\n\t\tassertNonNegativeSafeInteger(input.baseEntryCount, \"pi-server run state baseEntryCount\");\n\t\tif (input.baseLeafId !== null) {\n\t\t\tassertIdentifier(input.baseLeafId, \"pi-server run state baseLeafId\");\n\t\t}\n\t\tassertHash(input.requestHash, \"pi-server run state requestHash\");\n\t\tconst record: PiServerPendingRunState = {\n\t\t\tversion: RUN_STATE_VERSION,\n\t\t\tkind: \"run\",\n\t\t\tsequence: state.nextSequence,\n\t\t\ttimestamp,\n\t\t\tserverHash: input.serverHash,\n\t\t\tsessionId: input.sessionId,\n\t\t\trunId: input.runId,\n\t\t\tbaseTreeHash: input.baseTreeHash,\n\t\t\tbaseEntryCount: input.baseEntryCount,\n\t\t\tbaseLeafId: input.baseLeafId,\n\t\t\trequestHash: input.requestHash,\n\t\t};\n\t\tappendRecord(path, record);\n\t\treturn record;\n\t});\n}\n\nexport function acknowledgePiServerPendingRun(\n\tpath: string,\n\trunId: string,\n\ttimestamp = Date.now(),\n\tlease?: PiServerRunStateLease,\n): void {\n\twithRunStateLease(path, lease, () => {\n\t\tconst state = parseRunStateFile(path);\n\t\tif (!state.pending) return;\n\t\tif (state.pending.runId !== runId) {\n\t\t\tthrow new Error(`Cannot acknowledge pi-server run ${runId}; pending run is ${state.pending.runId}`);\n\t\t}\n\t\tassertNonNegativeSafeInteger(timestamp, \"pi-server run acknowledgement timestamp\");\n\t\tappendRecord(path, {\n\t\t\tversion: RUN_STATE_VERSION,\n\t\t\tkind: \"ack\",\n\t\t\tsequence: state.nextSequence,\n\t\t\ttimestamp,\n\t\t\trunId,\n\t\t\tresolution: \"server_ack\",\n\t\t});\n\t});\n}\n"]}
|