{"version":3,"file":"runtime-acknowledged-extensions.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/runtime-acknowledged-extensions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,uBAAuB,CAAC;AAElF,eAAO,MAAM,2BAA2B,mCAAmC,CAAC;AAC5E,eAAO,MAAM,8BAA8B,gDAAgD,CAAC;AAC5F,eAAO,MAAM,sCAAsC,KAAK,CAAC;AACzD,eAAO,MAAM,4CAA4C,MAAM,CAAC;AAEhE,eAAO,MAAM,6CAA6C,QAAY,CAAC;AAEvE,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAUhF;AAED,wBAAgB,oCAAoC,CACnD,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GACpB,oCAAoC,GAAG,SAAS,CAelD;AAED,wBAAgB,qCAAqC,CACpD,KAAK,EAAE,OAAO,GACZ,oCAAoC,GAAG,SAAS,CASlD;AAED,wBAAgB,iCAAiC,CAChD,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC1B,oCAAoC,GAAG,SAAS,CASlD;AAED,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI,CASjG","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { RuntimeAcknowledgedChildExtensionsV1 } from \"../../shared/types.ts\";\n\nexport const RUNTIME_EXTENSION_ACK_EVENT = \"subagent:acknowledge-extension\";\nexport const RUNTIME_EXTENSION_ACK_PATH_ENV = \"PI_SUBAGENT_RUNTIME_ACKNOWLEDGED_EXTENSIONS\";\nexport const MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_IDS = 32;\nexport const MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_ID_LENGTH = 128;\n// Generous bound for a valid capture (32 ids x 128 chars plus envelope); larger files are child misbehavior.\nexport const MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_FILE_BYTES = 64 * 1024;\n\nexport function isRuntimeAcknowledgedExtensionId(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_ID_LENGTH &&\n\t\t/^[A-Za-z0-9._:@+-]+$/.test(value) &&\n\t\t!value.includes(\"..\") &&\n\t\t!value.includes(\"/\") &&\n\t\t!value.includes(\"\\\\\")\n\t);\n}\n\nexport function projectRuntimeAcknowledgedExtensions(\n\tids: Iterable<unknown>,\n): RuntimeAcknowledgedChildExtensionsV1 | undefined {\n\tconst unique: string[] = [];\n\tconst seen = new Set<string>();\n\tfor (const id of ids) {\n\t\tif (!isRuntimeAcknowledgedExtensionId(id) || seen.has(id)) continue;\n\t\tseen.add(id);\n\t\tunique.push(id);\n\t}\n\tif (unique.length === 0) return undefined;\n\treturn {\n\t\tversion: 1,\n\t\tsource: \"child-runtime\",\n\t\tids: unique.slice(0, MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_IDS),\n\t\tomitted: Math.max(0, unique.length - MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_IDS),\n\t};\n}\n\nexport function sanitizeRuntimeAcknowledgedExtensions(\n\tvalue: unknown,\n): RuntimeAcknowledgedChildExtensionsV1 | undefined {\n\tif (!value || typeof value !== \"object\") return undefined;\n\tconst raw = value as Record<string, unknown>;\n\tif (raw.version !== 1 || raw.source !== \"child-runtime\" || !Array.isArray(raw.ids)) return undefined;\n\tconst projected = projectRuntimeAcknowledgedExtensions(raw.ids);\n\tif (!projected) return undefined;\n\tconst omitted =\n\t\ttypeof raw.omitted === \"number\" && Number.isFinite(raw.omitted) ? Math.max(0, Math.floor(raw.omitted)) : 0;\n\treturn { ...projected, omitted: projected.omitted + omitted };\n}\n\nexport function readRuntimeAcknowledgedExtensions(\n\tfilePath: string | undefined,\n): RuntimeAcknowledgedChildExtensionsV1 | undefined {\n\tif (!filePath) return undefined;\n\ttry {\n\t\tif (fs.statSync(filePath).size > MAX_RUNTIME_ACKNOWLEDGED_EXTENSION_FILE_BYTES) return undefined;\n\t\tconst parsed = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as unknown;\n\t\treturn sanitizeRuntimeAcknowledgedExtensions(parsed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function writeRuntimeAcknowledgedExtensions(filePath: string, ids: Iterable<unknown>): void {\n\tconst projection = projectRuntimeAcknowledgedExtensions(ids);\n\ttry {\n\t\tfs.mkdirSync(path.dirname(filePath), { recursive: true });\n\t\tif (projection) fs.writeFileSync(filePath, JSON.stringify(projection), { mode: 0o600 });\n\t\telse fs.rmSync(filePath, { force: true });\n\t} catch {\n\t\t// Runtime acknowledgement is best-effort observability only.\n\t}\n}\n"]}