@nexart/ai-execution 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +100 -330
  2. package/dist/index.cjs +607 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +56 -0
  5. package/dist/index.d.ts +55 -11
  6. package/dist/index.mjs +550 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/dist/providers/anthropic.cjs +258 -0
  9. package/dist/providers/anthropic.cjs.map +1 -0
  10. package/dist/providers/anthropic.d.cts +24 -0
  11. package/dist/providers/anthropic.d.ts +7 -5
  12. package/dist/providers/anthropic.mjs +221 -0
  13. package/dist/providers/anthropic.mjs.map +1 -0
  14. package/dist/providers/openai.cjs +259 -0
  15. package/dist/providers/openai.cjs.map +1 -0
  16. package/dist/providers/openai.d.cts +24 -0
  17. package/dist/providers/openai.d.ts +7 -5
  18. package/dist/providers/openai.mjs +222 -0
  19. package/dist/providers/openai.mjs.map +1 -0
  20. package/dist/providers/wrap.cjs +221 -0
  21. package/dist/providers/wrap.cjs.map +1 -0
  22. package/dist/providers/wrap.d.cts +9 -0
  23. package/dist/providers/wrap.d.ts +5 -3
  24. package/dist/providers/wrap.mjs +186 -0
  25. package/dist/providers/wrap.mjs.map +1 -0
  26. package/dist/{types.d.ts → types-DF29BsH5.d.cts} +18 -16
  27. package/dist/types-DF29BsH5.d.ts +155 -0
  28. package/package.json +18 -9
  29. package/dist/__tests__/fixtures.test.d.ts +0 -2
  30. package/dist/__tests__/fixtures.test.d.ts.map +0 -1
  31. package/dist/__tests__/fixtures.test.js +0 -37
  32. package/dist/__tests__/fixtures.test.js.map +0 -1
  33. package/dist/__tests__/v020.test.d.ts +0 -2
  34. package/dist/__tests__/v020.test.d.ts.map +0 -1
  35. package/dist/__tests__/v020.test.js +0 -408
  36. package/dist/__tests__/v020.test.js.map +0 -1
  37. package/dist/__tests__/vectors.test.d.ts +0 -2
  38. package/dist/__tests__/vectors.test.d.ts.map +0 -1
  39. package/dist/__tests__/vectors.test.js +0 -261
  40. package/dist/__tests__/vectors.test.js.map +0 -1
  41. package/dist/archive.d.ts +0 -4
  42. package/dist/archive.d.ts.map +0 -1
  43. package/dist/archive.js +0 -28
  44. package/dist/archive.js.map +0 -1
  45. package/dist/attest.d.ts +0 -3
  46. package/dist/attest.d.ts.map +0 -1
  47. package/dist/attest.js +0 -42
  48. package/dist/attest.js.map +0 -1
  49. package/dist/canonicalJson.d.ts +0 -2
  50. package/dist/canonicalJson.d.ts.map +0 -1
  51. package/dist/canonicalJson.js +0 -38
  52. package/dist/canonicalJson.js.map +0 -1
  53. package/dist/cer.d.ts +0 -7
  54. package/dist/cer.d.ts.map +0 -1
  55. package/dist/cer.js +0 -61
  56. package/dist/cer.js.map +0 -1
  57. package/dist/certify.d.ts +0 -3
  58. package/dist/certify.d.ts.map +0 -1
  59. package/dist/certify.js +0 -27
  60. package/dist/certify.js.map +0 -1
  61. package/dist/errors.d.ts +0 -10
  62. package/dist/errors.d.ts.map +0 -1
  63. package/dist/errors.js +0 -19
  64. package/dist/errors.js.map +0 -1
  65. package/dist/hash.d.ts +0 -6
  66. package/dist/hash.d.ts.map +0 -1
  67. package/dist/hash.js +0 -32
  68. package/dist/hash.js.map +0 -1
  69. package/dist/index.d.ts.map +0 -1
  70. package/dist/index.js +0 -11
  71. package/dist/index.js.map +0 -1
  72. package/dist/providers/anthropic.d.ts.map +0 -1
  73. package/dist/providers/anthropic.js +0 -61
  74. package/dist/providers/anthropic.js.map +0 -1
  75. package/dist/providers/openai.d.ts.map +0 -1
  76. package/dist/providers/openai.js +0 -62
  77. package/dist/providers/openai.js.map +0 -1
  78. package/dist/providers/wrap.d.ts.map +0 -1
  79. package/dist/providers/wrap.js +0 -28
  80. package/dist/providers/wrap.js.map +0 -1
  81. package/dist/run.d.ts +0 -14
  82. package/dist/run.d.ts.map +0 -1
  83. package/dist/run.js +0 -62
  84. package/dist/run.js.map +0 -1
  85. package/dist/snapshot.d.ts +0 -4
  86. package/dist/snapshot.d.ts.map +0 -1
  87. package/dist/snapshot.js +0 -113
  88. package/dist/snapshot.js.map +0 -1
  89. package/dist/types.d.ts.map +0 -1
  90. package/dist/types.js +0 -2
  91. package/dist/types.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hash.ts","../../src/canonicalJson.ts","../../src/snapshot.ts","../../src/cer.ts","../../src/providers/anthropic.ts"],"sourcesContent":["import * as crypto from 'crypto';\nimport { toCanonicalJson } from './canonicalJson.js';\n\nexport function sha256Hex(data: string | Uint8Array): string {\n const hash = crypto.createHash('sha256');\n if (typeof data === 'string') {\n hash.update(data, 'utf-8');\n } else {\n hash.update(data);\n }\n return hash.digest('hex');\n}\n\nexport function hashUtf8(value: string): string {\n return `sha256:${sha256Hex(value)}`;\n}\n\nexport function hashCanonicalJson(value: unknown): string {\n const canonical = toCanonicalJson(value);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function computeInputHash(input: string | Record<string, unknown>): string {\n if (typeof input === 'string') {\n return hashUtf8(input);\n }\n return hashCanonicalJson(input);\n}\n\nexport function computeOutputHash(output: string | Record<string, unknown>): string {\n if (typeof output === 'string') {\n return hashUtf8(output);\n }\n return hashCanonicalJson(output);\n}\n","export function toCanonicalJson(value: unknown): string {\n return canonicalize(value);\n}\n\nfunction canonicalize(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);\n }\n return JSON.stringify(value);\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n const items = value.map(item => canonicalize(item));\n return '[' + items.join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(key => {\n const val = obj[key];\n if (val === undefined) {\n return null;\n }\n return JSON.stringify(key) + ':' + canonicalize(val);\n }).filter(e => e !== null);\n return '{' + entries.join(',') + '}';\n }\n\n throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);\n}\n","import type { AiExecutionSnapshotV1, CreateSnapshotParams, VerificationResult, AiExecutionParameters } from './types.js';\nimport { computeInputHash, computeOutputHash } from './hash.js';\n\nconst PACKAGE_VERSION = '0.4.0';\n\nfunction validateParameters(params: AiExecutionParameters): string[] {\n const errors: string[] = [];\n\n if (typeof params.temperature !== 'number' || !Number.isFinite(params.temperature)) {\n errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);\n }\n\n if (typeof params.maxTokens !== 'number' || !Number.isFinite(params.maxTokens)) {\n errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);\n }\n\n if (params.topP !== null && (typeof params.topP !== 'number' || !Number.isFinite(params.topP))) {\n errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);\n }\n\n if (params.seed !== null && (typeof params.seed !== 'number' || !Number.isFinite(params.seed))) {\n errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);\n }\n\n return errors;\n}\n\nexport function createSnapshot(params: CreateSnapshotParams): AiExecutionSnapshotV1 {\n const paramErrors = validateParameters(params.parameters);\n if (paramErrors.length > 0) {\n throw new Error(`Invalid parameters: ${paramErrors.join('; ')}`);\n }\n\n const inputHash = computeInputHash(params.input);\n const outputHash = computeOutputHash(params.output);\n\n const snapshot: AiExecutionSnapshotV1 = {\n type: 'ai.execution.v1',\n protocolVersion: '1.2.0',\n executionSurface: 'ai',\n executionId: params.executionId,\n timestamp: params.timestamp ?? new Date().toISOString(),\n provider: params.provider,\n model: params.model,\n modelVersion: params.modelVersion ?? null,\n prompt: params.prompt,\n input: params.input,\n inputHash,\n parameters: {\n temperature: params.parameters.temperature,\n maxTokens: params.parameters.maxTokens,\n topP: params.parameters.topP ?? null,\n seed: params.parameters.seed ?? null,\n },\n output: params.output,\n outputHash,\n sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,\n appId: params.appId ?? null,\n };\n\n if (params.runId !== undefined) snapshot.runId = params.runId ?? null;\n if (params.stepId !== undefined) snapshot.stepId = params.stepId ?? null;\n if (params.stepIndex !== undefined) snapshot.stepIndex = params.stepIndex ?? null;\n if (params.workflowId !== undefined) snapshot.workflowId = params.workflowId ?? null;\n if (params.conversationId !== undefined) snapshot.conversationId = params.conversationId ?? null;\n if (params.prevStepHash !== undefined) snapshot.prevStepHash = params.prevStepHash ?? null;\n\n return snapshot;\n}\n\nexport function verifySnapshot(snapshot: AiExecutionSnapshotV1): VerificationResult {\n const errors: string[] = [];\n\n if (snapshot.type !== 'ai.execution.v1') {\n errors.push(`Expected type \"ai.execution.v1\", got \"${snapshot.type}\"`);\n }\n\n if (snapshot.protocolVersion !== '1.2.0') {\n errors.push(`Expected protocolVersion \"1.2.0\", got \"${snapshot.protocolVersion}\"`);\n }\n\n if (snapshot.executionSurface !== 'ai') {\n errors.push(`Expected executionSurface \"ai\", got \"${snapshot.executionSurface}\"`);\n }\n\n if (!snapshot.executionId || typeof snapshot.executionId !== 'string') {\n errors.push('executionId must be a non-empty string');\n }\n\n if (!snapshot.timestamp || typeof snapshot.timestamp !== 'string') {\n errors.push('timestamp must be a non-empty string');\n }\n\n if (!snapshot.provider || typeof snapshot.provider !== 'string') {\n errors.push('provider must be a non-empty string');\n }\n\n if (!snapshot.model || typeof snapshot.model !== 'string') {\n errors.push('model must be a non-empty string');\n }\n\n if (!snapshot.prompt || typeof snapshot.prompt !== 'string') {\n errors.push('prompt must be a non-empty string');\n }\n\n if (snapshot.input === undefined || snapshot.input === null) {\n errors.push('input must be a string or object');\n }\n\n if (snapshot.output === undefined || snapshot.output === null) {\n errors.push('output must be a string or object');\n }\n\n const paramErrors = validateParameters(snapshot.parameters);\n errors.push(...paramErrors);\n\n if (!snapshot.inputHash || !snapshot.inputHash.startsWith('sha256:')) {\n errors.push(`inputHash must start with \"sha256:\", got \"${snapshot.inputHash}\"`);\n }\n\n if (!snapshot.outputHash || !snapshot.outputHash.startsWith('sha256:')) {\n errors.push(`outputHash must start with \"sha256:\", got \"${snapshot.outputHash}\"`);\n }\n\n const expectedInputHash = computeInputHash(snapshot.input);\n if (snapshot.inputHash !== expectedInputHash) {\n errors.push(`inputHash mismatch: expected ${expectedInputHash}, got ${snapshot.inputHash}`);\n }\n\n const expectedOutputHash = computeOutputHash(snapshot.output);\n if (snapshot.outputHash !== expectedOutputHash) {\n errors.push(`outputHash mismatch: expected ${expectedOutputHash}, got ${snapshot.outputHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import type { AiExecutionSnapshotV1, CerAiExecutionBundle, CerMeta, VerificationResult } from './types.js';\nimport { toCanonicalJson } from './canonicalJson.js';\nimport { sha256Hex } from './hash.js';\nimport { verifySnapshot } from './snapshot.js';\n\ninterface CertificatePayload {\n bundleType: 'cer.ai.execution.v1';\n createdAt: string;\n snapshot: AiExecutionSnapshotV1;\n version: '0.1';\n}\n\nfunction computeCertificateHash(payload: CertificatePayload): string {\n const canonical = toCanonicalJson(payload);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function sealCer(\n snapshot: AiExecutionSnapshotV1,\n options?: { createdAt?: string; meta?: CerMeta }\n): CerAiExecutionBundle {\n const createdAt = options?.createdAt ?? new Date().toISOString();\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt,\n snapshot,\n version: '0.1',\n };\n\n const certificateHash = computeCertificateHash(payload);\n\n const bundle: CerAiExecutionBundle = {\n bundleType: 'cer.ai.execution.v1',\n certificateHash,\n createdAt,\n version: '0.1',\n snapshot,\n };\n\n if (options?.meta) {\n bundle.meta = options.meta;\n }\n\n return bundle;\n}\n\nexport function verifyCer(bundle: CerAiExecutionBundle): VerificationResult {\n const errors: string[] = [];\n\n if (bundle.bundleType !== 'cer.ai.execution.v1') {\n errors.push(`Expected bundleType \"cer.ai.execution.v1\", got \"${bundle.bundleType}\"`);\n }\n\n if (bundle.version !== '0.1') {\n errors.push(`Expected version \"0.1\", got \"${bundle.version}\"`);\n }\n\n if (!bundle.createdAt || typeof bundle.createdAt !== 'string') {\n errors.push('createdAt must be a non-empty string');\n }\n\n if (!bundle.certificateHash || !bundle.certificateHash.startsWith('sha256:')) {\n errors.push(`certificateHash must start with \"sha256:\", got \"${bundle.certificateHash}\"`);\n }\n\n if (!bundle.snapshot) {\n errors.push('snapshot is required');\n return { ok: false, errors };\n }\n\n const snapshotResult = verifySnapshot(bundle.snapshot);\n errors.push(...snapshotResult.errors);\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt: bundle.createdAt,\n snapshot: bundle.snapshot,\n version: '0.1',\n };\n\n const expectedHash = computeCertificateHash(payload);\n if (bundle.certificateHash !== expectedHash) {\n errors.push(`certificateHash mismatch: expected ${expectedHash}, got ${bundle.certificateHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import type { AiExecutionSnapshotV1, CerAiExecutionBundle } from '../types.js';\nimport { createSnapshot } from '../snapshot.js';\nimport { sealCer } from '../cer.js';\nimport * as crypto from 'crypto';\n\nexport interface AnthropicChatParams {\n prompt: string;\n input: string;\n model?: string;\n modelVersion?: string | null;\n parameters?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number | null;\n seed?: number | null;\n };\n appId?: string | null;\n apiKey?: string;\n}\n\nexport interface AnthropicChatResult {\n output: string;\n snapshot: AiExecutionSnapshotV1;\n bundle: CerAiExecutionBundle;\n}\n\nexport async function runAnthropicExecution(params: AnthropicChatParams): Promise<AnthropicChatResult> {\n const apiKey = params.apiKey || process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'Missing Anthropic API key. Set ANTHROPIC_API_KEY environment variable or pass apiKey in params.'\n );\n }\n\n const model = params.model ?? 'claude-sonnet-4-20250514';\n const temperature = params.parameters?.temperature ?? 0.7;\n const maxTokens = params.parameters?.maxTokens ?? 1024;\n const topP = params.parameters?.topP ?? null;\n const seed = params.parameters?.seed ?? null;\n\n const requestBody: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n messages: [\n { role: 'user', content: params.input },\n ],\n system: params.prompt,\n temperature,\n };\n\n if (topP !== null) {\n requestBody.top_p = topP;\n }\n\n const response = await fetch('https://api.anthropic.com/v1/messages', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': '2023-06-01',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Anthropic API error (${response.status}): ${errorText}`);\n }\n\n const json = await response.json() as {\n content: Array<{ type: string; text: string }>;\n model: string;\n };\n\n const textBlock = json.content.find(b => b.type === 'text');\n const output = textBlock?.text ?? '';\n\n const snapshot = createSnapshot({\n executionId: crypto.randomUUID(),\n provider: 'anthropic',\n model,\n modelVersion: params.modelVersion ?? json.model ?? null,\n prompt: params.prompt,\n input: params.input,\n parameters: {\n temperature,\n maxTokens,\n topP,\n seed,\n },\n output,\n appId: params.appId ?? null,\n });\n\n const bundle = sealCer(snapshot);\n\n return { output, snapshot, bundle };\n}\n"],"mappings":";AAAA,YAAY,YAAY;;;ACAjB,SAAS,gBAAgB,OAAwB;AACtD,SAAO,aAAa,KAAK;AAC3B;AAEA,SAAS,aAAa,OAAwB;AAC5C,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO,QAAQ,SAAS;AAAA,EAC1B;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC3B,YAAM,IAAI,MAAM,oDAAoD,KAAK,EAAE;AAAA,IAC7E;AACA,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,QAAQ,MAAM,IAAI,UAAQ,aAAa,IAAI,CAAC;AAClD,WAAO,MAAM,MAAM,KAAK,GAAG,IAAI;AAAA,EACjC;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,MAAM;AACZ,UAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AACnC,UAAM,UAAU,KAAK,IAAI,SAAO;AAC9B,YAAM,MAAM,IAAI,GAAG;AACnB,UAAI,QAAQ,QAAW;AACrB,eAAO;AAAA,MACT;AACA,aAAO,KAAK,UAAU,GAAG,IAAI,MAAM,aAAa,GAAG;AAAA,IACrD,CAAC,EAAE,OAAO,OAAK,MAAM,IAAI;AACzB,WAAO,MAAM,QAAQ,KAAK,GAAG,IAAI;AAAA,EACnC;AAEA,QAAM,IAAI,MAAM,wCAAwC,OAAO,KAAK,EAAE;AACxE;;;ADxCO,SAAS,UAAU,MAAmC;AAC3D,QAAM,OAAc,kBAAW,QAAQ;AACvC,MAAI,OAAO,SAAS,UAAU;AAC5B,SAAK,OAAO,MAAM,OAAO;AAAA,EAC3B,OAAO;AACL,SAAK,OAAO,IAAI;AAAA,EAClB;AACA,SAAO,KAAK,OAAO,KAAK;AAC1B;AAEO,SAAS,SAAS,OAAuB;AAC9C,SAAO,UAAU,UAAU,KAAK,CAAC;AACnC;AAEO,SAAS,kBAAkB,OAAwB;AACxD,QAAM,YAAY,gBAAgB,KAAK;AACvC,SAAO,UAAU,UAAU,SAAS,CAAC;AACvC;AAEO,SAAS,iBAAiB,OAAiD;AAChF,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,SAAS,KAAK;AAAA,EACvB;AACA,SAAO,kBAAkB,KAAK;AAChC;AAEO,SAAS,kBAAkB,QAAkD;AAClF,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,SAAS,MAAM;AAAA,EACxB;AACA,SAAO,kBAAkB,MAAM;AACjC;;;AE/BA,IAAM,kBAAkB;AAExB,SAAS,mBAAmB,QAAyC;AACnE,QAAM,SAAmB,CAAC;AAE1B,MAAI,OAAO,OAAO,gBAAgB,YAAY,CAAC,OAAO,SAAS,OAAO,WAAW,GAAG;AAClF,WAAO,KAAK,wDAAwD,OAAO,WAAW,EAAE;AAAA,EAC1F;AAEA,MAAI,OAAO,OAAO,cAAc,YAAY,CAAC,OAAO,SAAS,OAAO,SAAS,GAAG;AAC9E,WAAO,KAAK,sDAAsD,OAAO,SAAS,EAAE;AAAA,EACtF;AAEA,MAAI,OAAO,SAAS,SAAS,OAAO,OAAO,SAAS,YAAY,CAAC,OAAO,SAAS,OAAO,IAAI,IAAI;AAC9F,WAAO,KAAK,yDAAyD,OAAO,IAAI,EAAE;AAAA,EACpF;AAEA,MAAI,OAAO,SAAS,SAAS,OAAO,OAAO,SAAS,YAAY,CAAC,OAAO,SAAS,OAAO,IAAI,IAAI;AAC9F,WAAO,KAAK,yDAAyD,OAAO,IAAI,EAAE;AAAA,EACpF;AAEA,SAAO;AACT;AAEO,SAAS,eAAe,QAAqD;AAClF,QAAM,cAAc,mBAAmB,OAAO,UAAU;AACxD,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,IAAI,MAAM,uBAAuB,YAAY,KAAK,IAAI,CAAC,EAAE;AAAA,EACjE;AAEA,QAAM,YAAY,iBAAiB,OAAO,KAAK;AAC/C,QAAM,aAAa,kBAAkB,OAAO,MAAM;AAElD,QAAM,WAAkC;AAAA,IACtC,MAAM;AAAA,IACN,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,aAAa,OAAO;AAAA,IACpB,WAAW,OAAO,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtD,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,cAAc,OAAO,gBAAgB;AAAA,IACrC,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO;AAAA,IACd;AAAA,IACA,YAAY;AAAA,MACV,aAAa,OAAO,WAAW;AAAA,MAC/B,WAAW,OAAO,WAAW;AAAA,MAC7B,MAAM,OAAO,WAAW,QAAQ;AAAA,MAChC,MAAM,OAAO,WAAW,QAAQ;AAAA,IAClC;AAAA,IACA,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,YAAY,OAAO,cAAc;AAAA,IACjC,OAAO,OAAO,SAAS;AAAA,EACzB;AAEA,MAAI,OAAO,UAAU,OAAW,UAAS,QAAQ,OAAO,SAAS;AACjE,MAAI,OAAO,WAAW,OAAW,UAAS,SAAS,OAAO,UAAU;AACpE,MAAI,OAAO,cAAc,OAAW,UAAS,YAAY,OAAO,aAAa;AAC7E,MAAI,OAAO,eAAe,OAAW,UAAS,aAAa,OAAO,cAAc;AAChF,MAAI,OAAO,mBAAmB,OAAW,UAAS,iBAAiB,OAAO,kBAAkB;AAC5F,MAAI,OAAO,iBAAiB,OAAW,UAAS,eAAe,OAAO,gBAAgB;AAEtF,SAAO;AACT;;;ACxDA,SAAS,uBAAuB,SAAqC;AACnE,QAAM,YAAY,gBAAgB,OAAO;AACzC,SAAO,UAAU,UAAU,SAAS,CAAC;AACvC;AAEO,SAAS,QACd,UACA,SACsB;AACtB,QAAM,YAAY,SAAS,cAAa,oBAAI,KAAK,GAAE,YAAY;AAE/D,QAAM,UAA8B;AAAA,IAClC,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,SAAS;AAAA,EACX;AAEA,QAAM,kBAAkB,uBAAuB,OAAO;AAEtD,QAAM,SAA+B;AAAA,IACnC,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,EACF;AAEA,MAAI,SAAS,MAAM;AACjB,WAAO,OAAO,QAAQ;AAAA,EACxB;AAEA,SAAO;AACT;;;AC1CA,YAAYA,aAAY;AAuBxB,eAAsB,sBAAsB,QAA2D;AACrG,QAAM,SAAS,OAAO,UAAU,QAAQ,IAAI;AAC5C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,cAAc,OAAO,YAAY,eAAe;AACtD,QAAM,YAAY,OAAO,YAAY,aAAa;AAClD,QAAM,OAAO,OAAO,YAAY,QAAQ;AACxC,QAAM,OAAO,OAAO,YAAY,QAAQ;AAExC,QAAM,cAAuC;AAAA,IAC3C;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,MACR,EAAE,MAAM,QAAQ,SAAS,OAAO,MAAM;AAAA,IACxC;AAAA,IACA,QAAQ,OAAO;AAAA,IACf;AAAA,EACF;AAEA,MAAI,SAAS,MAAM;AACjB,gBAAY,QAAQ;AAAA,EACtB;AAEA,QAAM,WAAW,MAAM,MAAM,yCAAyC;AAAA,IACpE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,qBAAqB;AAAA,IACvB;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,EAClC,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,YAAY,MAAM,SAAS,KAAK;AACtC,UAAM,IAAI,MAAM,wBAAwB,SAAS,MAAM,MAAM,SAAS,EAAE;AAAA,EAC1E;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AAKjC,QAAM,YAAY,KAAK,QAAQ,KAAK,OAAK,EAAE,SAAS,MAAM;AAC1D,QAAM,SAAS,WAAW,QAAQ;AAElC,QAAM,WAAW,eAAe;AAAA,IAC9B,aAAoB,mBAAW;AAAA,IAC/B,UAAU;AAAA,IACV;AAAA,IACA,cAAc,OAAO,gBAAgB,KAAK,SAAS;AAAA,IACnD,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO;AAAA,IACd,YAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,IACA,OAAO,OAAO,SAAS;AAAA,EACzB,CAAC;AAED,QAAM,SAAS,QAAQ,QAAQ;AAE/B,SAAO,EAAE,QAAQ,UAAU,OAAO;AACpC;","names":["crypto"]}
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/providers/openai.ts
31
+ var openai_exports = {};
32
+ __export(openai_exports, {
33
+ runOpenAIChatExecution: () => runOpenAIChatExecution
34
+ });
35
+ module.exports = __toCommonJS(openai_exports);
36
+
37
+ // src/hash.ts
38
+ var crypto = __toESM(require("crypto"), 1);
39
+
40
+ // src/canonicalJson.ts
41
+ function toCanonicalJson(value) {
42
+ return canonicalize(value);
43
+ }
44
+ function canonicalize(value) {
45
+ if (value === null) {
46
+ return "null";
47
+ }
48
+ if (typeof value === "boolean") {
49
+ return value ? "true" : "false";
50
+ }
51
+ if (typeof value === "number") {
52
+ if (!Number.isFinite(value)) {
53
+ throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);
54
+ }
55
+ return JSON.stringify(value);
56
+ }
57
+ if (typeof value === "string") {
58
+ return JSON.stringify(value);
59
+ }
60
+ if (Array.isArray(value)) {
61
+ const items = value.map((item) => canonicalize(item));
62
+ return "[" + items.join(",") + "]";
63
+ }
64
+ if (typeof value === "object") {
65
+ const obj = value;
66
+ const keys = Object.keys(obj).sort();
67
+ const entries = keys.map((key) => {
68
+ const val = obj[key];
69
+ if (val === void 0) {
70
+ return null;
71
+ }
72
+ return JSON.stringify(key) + ":" + canonicalize(val);
73
+ }).filter((e) => e !== null);
74
+ return "{" + entries.join(",") + "}";
75
+ }
76
+ throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);
77
+ }
78
+
79
+ // src/hash.ts
80
+ function sha256Hex(data) {
81
+ const hash = crypto.createHash("sha256");
82
+ if (typeof data === "string") {
83
+ hash.update(data, "utf-8");
84
+ } else {
85
+ hash.update(data);
86
+ }
87
+ return hash.digest("hex");
88
+ }
89
+ function hashUtf8(value) {
90
+ return `sha256:${sha256Hex(value)}`;
91
+ }
92
+ function hashCanonicalJson(value) {
93
+ const canonical = toCanonicalJson(value);
94
+ return `sha256:${sha256Hex(canonical)}`;
95
+ }
96
+ function computeInputHash(input) {
97
+ if (typeof input === "string") {
98
+ return hashUtf8(input);
99
+ }
100
+ return hashCanonicalJson(input);
101
+ }
102
+ function computeOutputHash(output) {
103
+ if (typeof output === "string") {
104
+ return hashUtf8(output);
105
+ }
106
+ return hashCanonicalJson(output);
107
+ }
108
+
109
+ // src/snapshot.ts
110
+ var PACKAGE_VERSION = "0.4.0";
111
+ function validateParameters(params) {
112
+ const errors = [];
113
+ if (typeof params.temperature !== "number" || !Number.isFinite(params.temperature)) {
114
+ errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);
115
+ }
116
+ if (typeof params.maxTokens !== "number" || !Number.isFinite(params.maxTokens)) {
117
+ errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);
118
+ }
119
+ if (params.topP !== null && (typeof params.topP !== "number" || !Number.isFinite(params.topP))) {
120
+ errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);
121
+ }
122
+ if (params.seed !== null && (typeof params.seed !== "number" || !Number.isFinite(params.seed))) {
123
+ errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);
124
+ }
125
+ return errors;
126
+ }
127
+ function createSnapshot(params) {
128
+ const paramErrors = validateParameters(params.parameters);
129
+ if (paramErrors.length > 0) {
130
+ throw new Error(`Invalid parameters: ${paramErrors.join("; ")}`);
131
+ }
132
+ const inputHash = computeInputHash(params.input);
133
+ const outputHash = computeOutputHash(params.output);
134
+ const snapshot = {
135
+ type: "ai.execution.v1",
136
+ protocolVersion: "1.2.0",
137
+ executionSurface: "ai",
138
+ executionId: params.executionId,
139
+ timestamp: params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
140
+ provider: params.provider,
141
+ model: params.model,
142
+ modelVersion: params.modelVersion ?? null,
143
+ prompt: params.prompt,
144
+ input: params.input,
145
+ inputHash,
146
+ parameters: {
147
+ temperature: params.parameters.temperature,
148
+ maxTokens: params.parameters.maxTokens,
149
+ topP: params.parameters.topP ?? null,
150
+ seed: params.parameters.seed ?? null
151
+ },
152
+ output: params.output,
153
+ outputHash,
154
+ sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,
155
+ appId: params.appId ?? null
156
+ };
157
+ if (params.runId !== void 0) snapshot.runId = params.runId ?? null;
158
+ if (params.stepId !== void 0) snapshot.stepId = params.stepId ?? null;
159
+ if (params.stepIndex !== void 0) snapshot.stepIndex = params.stepIndex ?? null;
160
+ if (params.workflowId !== void 0) snapshot.workflowId = params.workflowId ?? null;
161
+ if (params.conversationId !== void 0) snapshot.conversationId = params.conversationId ?? null;
162
+ if (params.prevStepHash !== void 0) snapshot.prevStepHash = params.prevStepHash ?? null;
163
+ return snapshot;
164
+ }
165
+
166
+ // src/cer.ts
167
+ function computeCertificateHash(payload) {
168
+ const canonical = toCanonicalJson(payload);
169
+ return `sha256:${sha256Hex(canonical)}`;
170
+ }
171
+ function sealCer(snapshot, options) {
172
+ const createdAt = options?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
173
+ const payload = {
174
+ bundleType: "cer.ai.execution.v1",
175
+ createdAt,
176
+ snapshot,
177
+ version: "0.1"
178
+ };
179
+ const certificateHash = computeCertificateHash(payload);
180
+ const bundle = {
181
+ bundleType: "cer.ai.execution.v1",
182
+ certificateHash,
183
+ createdAt,
184
+ version: "0.1",
185
+ snapshot
186
+ };
187
+ if (options?.meta) {
188
+ bundle.meta = options.meta;
189
+ }
190
+ return bundle;
191
+ }
192
+
193
+ // src/providers/openai.ts
194
+ var crypto2 = __toESM(require("crypto"), 1);
195
+ async function runOpenAIChatExecution(params) {
196
+ const apiKey = params.apiKey || process.env.OPENAI_API_KEY;
197
+ if (!apiKey) {
198
+ throw new Error(
199
+ "Missing OpenAI API key. Set OPENAI_API_KEY environment variable or pass apiKey in params."
200
+ );
201
+ }
202
+ const model = params.model ?? "gpt-4o";
203
+ const temperature = params.parameters?.temperature ?? 0.7;
204
+ const maxTokens = params.parameters?.maxTokens ?? 1024;
205
+ const topP = params.parameters?.topP ?? null;
206
+ const seed = params.parameters?.seed ?? null;
207
+ const requestBody = {
208
+ model,
209
+ messages: [
210
+ { role: "system", content: params.prompt },
211
+ { role: "user", content: params.input }
212
+ ],
213
+ temperature,
214
+ max_tokens: maxTokens
215
+ };
216
+ if (topP !== null) {
217
+ requestBody.top_p = topP;
218
+ }
219
+ if (seed !== null) {
220
+ requestBody.seed = seed;
221
+ }
222
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
223
+ method: "POST",
224
+ headers: {
225
+ "Content-Type": "application/json",
226
+ "Authorization": `Bearer ${apiKey}`
227
+ },
228
+ body: JSON.stringify(requestBody)
229
+ });
230
+ if (!response.ok) {
231
+ const errorText = await response.text();
232
+ throw new Error(`OpenAI API error (${response.status}): ${errorText}`);
233
+ }
234
+ const json = await response.json();
235
+ const output = json.choices[0]?.message?.content ?? "";
236
+ const snapshot = createSnapshot({
237
+ executionId: crypto2.randomUUID(),
238
+ provider: "openai",
239
+ model,
240
+ modelVersion: params.modelVersion ?? json.model ?? null,
241
+ prompt: params.prompt,
242
+ input: params.input,
243
+ parameters: {
244
+ temperature,
245
+ maxTokens,
246
+ topP,
247
+ seed
248
+ },
249
+ output,
250
+ appId: params.appId ?? null
251
+ });
252
+ const bundle = sealCer(snapshot);
253
+ return { output, snapshot, bundle };
254
+ }
255
+ // Annotate the CommonJS export names for ESM import in node:
256
+ 0 && (module.exports = {
257
+ runOpenAIChatExecution
258
+ });
259
+ //# sourceMappingURL=openai.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/openai.ts","../../src/hash.ts","../../src/canonicalJson.ts","../../src/snapshot.ts","../../src/cer.ts"],"sourcesContent":["import type { AiExecutionSnapshotV1, CerAiExecutionBundle } from '../types.js';\nimport { createSnapshot } from '../snapshot.js';\nimport { sealCer } from '../cer.js';\nimport * as crypto from 'crypto';\n\nexport interface OpenAIChatParams {\n prompt: string;\n input: string;\n model?: string;\n modelVersion?: string | null;\n parameters?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number | null;\n seed?: number | null;\n };\n appId?: string | null;\n apiKey?: string;\n}\n\nexport interface OpenAIChatResult {\n output: string;\n snapshot: AiExecutionSnapshotV1;\n bundle: CerAiExecutionBundle;\n}\n\nexport async function runOpenAIChatExecution(params: OpenAIChatParams): Promise<OpenAIChatResult> {\n const apiKey = params.apiKey || process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'Missing OpenAI API key. Set OPENAI_API_KEY environment variable or pass apiKey in params.'\n );\n }\n\n const model = params.model ?? 'gpt-4o';\n const temperature = params.parameters?.temperature ?? 0.7;\n const maxTokens = params.parameters?.maxTokens ?? 1024;\n const topP = params.parameters?.topP ?? null;\n const seed = params.parameters?.seed ?? null;\n\n const requestBody: Record<string, unknown> = {\n model,\n messages: [\n { role: 'system', content: params.prompt },\n { role: 'user', content: params.input },\n ],\n temperature,\n max_tokens: maxTokens,\n };\n\n if (topP !== null) {\n requestBody.top_p = topP;\n }\n if (seed !== null) {\n requestBody.seed = seed;\n }\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`OpenAI API error (${response.status}): ${errorText}`);\n }\n\n const json = await response.json() as {\n choices: Array<{ message: { content: string } }>;\n model: string;\n };\n\n const output = json.choices[0]?.message?.content ?? '';\n\n const snapshot = createSnapshot({\n executionId: crypto.randomUUID(),\n provider: 'openai',\n model,\n modelVersion: params.modelVersion ?? json.model ?? null,\n prompt: params.prompt,\n input: params.input,\n parameters: {\n temperature,\n maxTokens,\n topP,\n seed,\n },\n output,\n appId: params.appId ?? null,\n });\n\n const bundle = sealCer(snapshot);\n\n return { output, snapshot, bundle };\n}\n","import * as crypto from 'crypto';\nimport { toCanonicalJson } from './canonicalJson.js';\n\nexport function sha256Hex(data: string | Uint8Array): string {\n const hash = crypto.createHash('sha256');\n if (typeof data === 'string') {\n hash.update(data, 'utf-8');\n } else {\n hash.update(data);\n }\n return hash.digest('hex');\n}\n\nexport function hashUtf8(value: string): string {\n return `sha256:${sha256Hex(value)}`;\n}\n\nexport function hashCanonicalJson(value: unknown): string {\n const canonical = toCanonicalJson(value);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function computeInputHash(input: string | Record<string, unknown>): string {\n if (typeof input === 'string') {\n return hashUtf8(input);\n }\n return hashCanonicalJson(input);\n}\n\nexport function computeOutputHash(output: string | Record<string, unknown>): string {\n if (typeof output === 'string') {\n return hashUtf8(output);\n }\n return hashCanonicalJson(output);\n}\n","export function toCanonicalJson(value: unknown): string {\n return canonicalize(value);\n}\n\nfunction canonicalize(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);\n }\n return JSON.stringify(value);\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n const items = value.map(item => canonicalize(item));\n return '[' + items.join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(key => {\n const val = obj[key];\n if (val === undefined) {\n return null;\n }\n return JSON.stringify(key) + ':' + canonicalize(val);\n }).filter(e => e !== null);\n return '{' + entries.join(',') + '}';\n }\n\n throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);\n}\n","import type { AiExecutionSnapshotV1, CreateSnapshotParams, VerificationResult, AiExecutionParameters } from './types.js';\nimport { computeInputHash, computeOutputHash } from './hash.js';\n\nconst PACKAGE_VERSION = '0.4.0';\n\nfunction validateParameters(params: AiExecutionParameters): string[] {\n const errors: string[] = [];\n\n if (typeof params.temperature !== 'number' || !Number.isFinite(params.temperature)) {\n errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);\n }\n\n if (typeof params.maxTokens !== 'number' || !Number.isFinite(params.maxTokens)) {\n errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);\n }\n\n if (params.topP !== null && (typeof params.topP !== 'number' || !Number.isFinite(params.topP))) {\n errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);\n }\n\n if (params.seed !== null && (typeof params.seed !== 'number' || !Number.isFinite(params.seed))) {\n errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);\n }\n\n return errors;\n}\n\nexport function createSnapshot(params: CreateSnapshotParams): AiExecutionSnapshotV1 {\n const paramErrors = validateParameters(params.parameters);\n if (paramErrors.length > 0) {\n throw new Error(`Invalid parameters: ${paramErrors.join('; ')}`);\n }\n\n const inputHash = computeInputHash(params.input);\n const outputHash = computeOutputHash(params.output);\n\n const snapshot: AiExecutionSnapshotV1 = {\n type: 'ai.execution.v1',\n protocolVersion: '1.2.0',\n executionSurface: 'ai',\n executionId: params.executionId,\n timestamp: params.timestamp ?? new Date().toISOString(),\n provider: params.provider,\n model: params.model,\n modelVersion: params.modelVersion ?? null,\n prompt: params.prompt,\n input: params.input,\n inputHash,\n parameters: {\n temperature: params.parameters.temperature,\n maxTokens: params.parameters.maxTokens,\n topP: params.parameters.topP ?? null,\n seed: params.parameters.seed ?? null,\n },\n output: params.output,\n outputHash,\n sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,\n appId: params.appId ?? null,\n };\n\n if (params.runId !== undefined) snapshot.runId = params.runId ?? null;\n if (params.stepId !== undefined) snapshot.stepId = params.stepId ?? null;\n if (params.stepIndex !== undefined) snapshot.stepIndex = params.stepIndex ?? null;\n if (params.workflowId !== undefined) snapshot.workflowId = params.workflowId ?? null;\n if (params.conversationId !== undefined) snapshot.conversationId = params.conversationId ?? null;\n if (params.prevStepHash !== undefined) snapshot.prevStepHash = params.prevStepHash ?? null;\n\n return snapshot;\n}\n\nexport function verifySnapshot(snapshot: AiExecutionSnapshotV1): VerificationResult {\n const errors: string[] = [];\n\n if (snapshot.type !== 'ai.execution.v1') {\n errors.push(`Expected type \"ai.execution.v1\", got \"${snapshot.type}\"`);\n }\n\n if (snapshot.protocolVersion !== '1.2.0') {\n errors.push(`Expected protocolVersion \"1.2.0\", got \"${snapshot.protocolVersion}\"`);\n }\n\n if (snapshot.executionSurface !== 'ai') {\n errors.push(`Expected executionSurface \"ai\", got \"${snapshot.executionSurface}\"`);\n }\n\n if (!snapshot.executionId || typeof snapshot.executionId !== 'string') {\n errors.push('executionId must be a non-empty string');\n }\n\n if (!snapshot.timestamp || typeof snapshot.timestamp !== 'string') {\n errors.push('timestamp must be a non-empty string');\n }\n\n if (!snapshot.provider || typeof snapshot.provider !== 'string') {\n errors.push('provider must be a non-empty string');\n }\n\n if (!snapshot.model || typeof snapshot.model !== 'string') {\n errors.push('model must be a non-empty string');\n }\n\n if (!snapshot.prompt || typeof snapshot.prompt !== 'string') {\n errors.push('prompt must be a non-empty string');\n }\n\n if (snapshot.input === undefined || snapshot.input === null) {\n errors.push('input must be a string or object');\n }\n\n if (snapshot.output === undefined || snapshot.output === null) {\n errors.push('output must be a string or object');\n }\n\n const paramErrors = validateParameters(snapshot.parameters);\n errors.push(...paramErrors);\n\n if (!snapshot.inputHash || !snapshot.inputHash.startsWith('sha256:')) {\n errors.push(`inputHash must start with \"sha256:\", got \"${snapshot.inputHash}\"`);\n }\n\n if (!snapshot.outputHash || !snapshot.outputHash.startsWith('sha256:')) {\n errors.push(`outputHash must start with \"sha256:\", got \"${snapshot.outputHash}\"`);\n }\n\n const expectedInputHash = computeInputHash(snapshot.input);\n if (snapshot.inputHash !== expectedInputHash) {\n errors.push(`inputHash mismatch: expected ${expectedInputHash}, got ${snapshot.inputHash}`);\n }\n\n const expectedOutputHash = computeOutputHash(snapshot.output);\n if (snapshot.outputHash !== expectedOutputHash) {\n errors.push(`outputHash mismatch: expected ${expectedOutputHash}, got ${snapshot.outputHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import type { AiExecutionSnapshotV1, CerAiExecutionBundle, CerMeta, VerificationResult } from './types.js';\nimport { toCanonicalJson } from './canonicalJson.js';\nimport { sha256Hex } from './hash.js';\nimport { verifySnapshot } from './snapshot.js';\n\ninterface CertificatePayload {\n bundleType: 'cer.ai.execution.v1';\n createdAt: string;\n snapshot: AiExecutionSnapshotV1;\n version: '0.1';\n}\n\nfunction computeCertificateHash(payload: CertificatePayload): string {\n const canonical = toCanonicalJson(payload);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function sealCer(\n snapshot: AiExecutionSnapshotV1,\n options?: { createdAt?: string; meta?: CerMeta }\n): CerAiExecutionBundle {\n const createdAt = options?.createdAt ?? new Date().toISOString();\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt,\n snapshot,\n version: '0.1',\n };\n\n const certificateHash = computeCertificateHash(payload);\n\n const bundle: CerAiExecutionBundle = {\n bundleType: 'cer.ai.execution.v1',\n certificateHash,\n createdAt,\n version: '0.1',\n snapshot,\n };\n\n if (options?.meta) {\n bundle.meta = options.meta;\n }\n\n return bundle;\n}\n\nexport function verifyCer(bundle: CerAiExecutionBundle): VerificationResult {\n const errors: string[] = [];\n\n if (bundle.bundleType !== 'cer.ai.execution.v1') {\n errors.push(`Expected bundleType \"cer.ai.execution.v1\", got \"${bundle.bundleType}\"`);\n }\n\n if (bundle.version !== '0.1') {\n errors.push(`Expected version \"0.1\", got \"${bundle.version}\"`);\n }\n\n if (!bundle.createdAt || typeof bundle.createdAt !== 'string') {\n errors.push('createdAt must be a non-empty string');\n }\n\n if (!bundle.certificateHash || !bundle.certificateHash.startsWith('sha256:')) {\n errors.push(`certificateHash must start with \"sha256:\", got \"${bundle.certificateHash}\"`);\n }\n\n if (!bundle.snapshot) {\n errors.push('snapshot is required');\n return { ok: false, errors };\n }\n\n const snapshotResult = verifySnapshot(bundle.snapshot);\n errors.push(...snapshotResult.errors);\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt: bundle.createdAt,\n snapshot: bundle.snapshot,\n version: '0.1',\n };\n\n const expectedHash = computeCertificateHash(payload);\n if (bundle.certificateHash !== expectedHash) {\n errors.push(`certificateHash mismatch: expected ${expectedHash}, got ${bundle.certificateHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n"],"mappings":"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","names":["crypto"]}
@@ -0,0 +1,24 @@
1
+ import { A as AiExecutionSnapshotV1, b as CerAiExecutionBundle } from '../types-DF29BsH5.cjs';
2
+
3
+ interface OpenAIChatParams {
4
+ prompt: string;
5
+ input: string;
6
+ model?: string;
7
+ modelVersion?: string | null;
8
+ parameters?: {
9
+ temperature?: number;
10
+ maxTokens?: number;
11
+ topP?: number | null;
12
+ seed?: number | null;
13
+ };
14
+ appId?: string | null;
15
+ apiKey?: string;
16
+ }
17
+ interface OpenAIChatResult {
18
+ output: string;
19
+ snapshot: AiExecutionSnapshotV1;
20
+ bundle: CerAiExecutionBundle;
21
+ }
22
+ declare function runOpenAIChatExecution(params: OpenAIChatParams): Promise<OpenAIChatResult>;
23
+
24
+ export { type OpenAIChatParams, type OpenAIChatResult, runOpenAIChatExecution };
@@ -1,5 +1,6 @@
1
- import type { AiExecutionSnapshotV1, CerAiExecutionBundle } from '../types.js';
2
- export interface OpenAIChatParams {
1
+ import { A as AiExecutionSnapshotV1, b as CerAiExecutionBundle } from '../types-DF29BsH5.js';
2
+
3
+ interface OpenAIChatParams {
3
4
  prompt: string;
4
5
  input: string;
5
6
  model?: string;
@@ -13,10 +14,11 @@ export interface OpenAIChatParams {
13
14
  appId?: string | null;
14
15
  apiKey?: string;
15
16
  }
16
- export interface OpenAIChatResult {
17
+ interface OpenAIChatResult {
17
18
  output: string;
18
19
  snapshot: AiExecutionSnapshotV1;
19
20
  bundle: CerAiExecutionBundle;
20
21
  }
21
- export declare function runOpenAIChatExecution(params: OpenAIChatParams): Promise<OpenAIChatResult>;
22
- //# sourceMappingURL=openai.d.ts.map
22
+ declare function runOpenAIChatExecution(params: OpenAIChatParams): Promise<OpenAIChatResult>;
23
+
24
+ export { type OpenAIChatParams, type OpenAIChatResult, runOpenAIChatExecution };
@@ -0,0 +1,222 @@
1
+ // src/hash.ts
2
+ import * as crypto from "crypto";
3
+
4
+ // src/canonicalJson.ts
5
+ function toCanonicalJson(value) {
6
+ return canonicalize(value);
7
+ }
8
+ function canonicalize(value) {
9
+ if (value === null) {
10
+ return "null";
11
+ }
12
+ if (typeof value === "boolean") {
13
+ return value ? "true" : "false";
14
+ }
15
+ if (typeof value === "number") {
16
+ if (!Number.isFinite(value)) {
17
+ throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);
18
+ }
19
+ return JSON.stringify(value);
20
+ }
21
+ if (typeof value === "string") {
22
+ return JSON.stringify(value);
23
+ }
24
+ if (Array.isArray(value)) {
25
+ const items = value.map((item) => canonicalize(item));
26
+ return "[" + items.join(",") + "]";
27
+ }
28
+ if (typeof value === "object") {
29
+ const obj = value;
30
+ const keys = Object.keys(obj).sort();
31
+ const entries = keys.map((key) => {
32
+ const val = obj[key];
33
+ if (val === void 0) {
34
+ return null;
35
+ }
36
+ return JSON.stringify(key) + ":" + canonicalize(val);
37
+ }).filter((e) => e !== null);
38
+ return "{" + entries.join(",") + "}";
39
+ }
40
+ throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);
41
+ }
42
+
43
+ // src/hash.ts
44
+ function sha256Hex(data) {
45
+ const hash = crypto.createHash("sha256");
46
+ if (typeof data === "string") {
47
+ hash.update(data, "utf-8");
48
+ } else {
49
+ hash.update(data);
50
+ }
51
+ return hash.digest("hex");
52
+ }
53
+ function hashUtf8(value) {
54
+ return `sha256:${sha256Hex(value)}`;
55
+ }
56
+ function hashCanonicalJson(value) {
57
+ const canonical = toCanonicalJson(value);
58
+ return `sha256:${sha256Hex(canonical)}`;
59
+ }
60
+ function computeInputHash(input) {
61
+ if (typeof input === "string") {
62
+ return hashUtf8(input);
63
+ }
64
+ return hashCanonicalJson(input);
65
+ }
66
+ function computeOutputHash(output) {
67
+ if (typeof output === "string") {
68
+ return hashUtf8(output);
69
+ }
70
+ return hashCanonicalJson(output);
71
+ }
72
+
73
+ // src/snapshot.ts
74
+ var PACKAGE_VERSION = "0.4.0";
75
+ function validateParameters(params) {
76
+ const errors = [];
77
+ if (typeof params.temperature !== "number" || !Number.isFinite(params.temperature)) {
78
+ errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);
79
+ }
80
+ if (typeof params.maxTokens !== "number" || !Number.isFinite(params.maxTokens)) {
81
+ errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);
82
+ }
83
+ if (params.topP !== null && (typeof params.topP !== "number" || !Number.isFinite(params.topP))) {
84
+ errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);
85
+ }
86
+ if (params.seed !== null && (typeof params.seed !== "number" || !Number.isFinite(params.seed))) {
87
+ errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);
88
+ }
89
+ return errors;
90
+ }
91
+ function createSnapshot(params) {
92
+ const paramErrors = validateParameters(params.parameters);
93
+ if (paramErrors.length > 0) {
94
+ throw new Error(`Invalid parameters: ${paramErrors.join("; ")}`);
95
+ }
96
+ const inputHash = computeInputHash(params.input);
97
+ const outputHash = computeOutputHash(params.output);
98
+ const snapshot = {
99
+ type: "ai.execution.v1",
100
+ protocolVersion: "1.2.0",
101
+ executionSurface: "ai",
102
+ executionId: params.executionId,
103
+ timestamp: params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
104
+ provider: params.provider,
105
+ model: params.model,
106
+ modelVersion: params.modelVersion ?? null,
107
+ prompt: params.prompt,
108
+ input: params.input,
109
+ inputHash,
110
+ parameters: {
111
+ temperature: params.parameters.temperature,
112
+ maxTokens: params.parameters.maxTokens,
113
+ topP: params.parameters.topP ?? null,
114
+ seed: params.parameters.seed ?? null
115
+ },
116
+ output: params.output,
117
+ outputHash,
118
+ sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,
119
+ appId: params.appId ?? null
120
+ };
121
+ if (params.runId !== void 0) snapshot.runId = params.runId ?? null;
122
+ if (params.stepId !== void 0) snapshot.stepId = params.stepId ?? null;
123
+ if (params.stepIndex !== void 0) snapshot.stepIndex = params.stepIndex ?? null;
124
+ if (params.workflowId !== void 0) snapshot.workflowId = params.workflowId ?? null;
125
+ if (params.conversationId !== void 0) snapshot.conversationId = params.conversationId ?? null;
126
+ if (params.prevStepHash !== void 0) snapshot.prevStepHash = params.prevStepHash ?? null;
127
+ return snapshot;
128
+ }
129
+
130
+ // src/cer.ts
131
+ function computeCertificateHash(payload) {
132
+ const canonical = toCanonicalJson(payload);
133
+ return `sha256:${sha256Hex(canonical)}`;
134
+ }
135
+ function sealCer(snapshot, options) {
136
+ const createdAt = options?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
137
+ const payload = {
138
+ bundleType: "cer.ai.execution.v1",
139
+ createdAt,
140
+ snapshot,
141
+ version: "0.1"
142
+ };
143
+ const certificateHash = computeCertificateHash(payload);
144
+ const bundle = {
145
+ bundleType: "cer.ai.execution.v1",
146
+ certificateHash,
147
+ createdAt,
148
+ version: "0.1",
149
+ snapshot
150
+ };
151
+ if (options?.meta) {
152
+ bundle.meta = options.meta;
153
+ }
154
+ return bundle;
155
+ }
156
+
157
+ // src/providers/openai.ts
158
+ import * as crypto2 from "crypto";
159
+ async function runOpenAIChatExecution(params) {
160
+ const apiKey = params.apiKey || process.env.OPENAI_API_KEY;
161
+ if (!apiKey) {
162
+ throw new Error(
163
+ "Missing OpenAI API key. Set OPENAI_API_KEY environment variable or pass apiKey in params."
164
+ );
165
+ }
166
+ const model = params.model ?? "gpt-4o";
167
+ const temperature = params.parameters?.temperature ?? 0.7;
168
+ const maxTokens = params.parameters?.maxTokens ?? 1024;
169
+ const topP = params.parameters?.topP ?? null;
170
+ const seed = params.parameters?.seed ?? null;
171
+ const requestBody = {
172
+ model,
173
+ messages: [
174
+ { role: "system", content: params.prompt },
175
+ { role: "user", content: params.input }
176
+ ],
177
+ temperature,
178
+ max_tokens: maxTokens
179
+ };
180
+ if (topP !== null) {
181
+ requestBody.top_p = topP;
182
+ }
183
+ if (seed !== null) {
184
+ requestBody.seed = seed;
185
+ }
186
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
187
+ method: "POST",
188
+ headers: {
189
+ "Content-Type": "application/json",
190
+ "Authorization": `Bearer ${apiKey}`
191
+ },
192
+ body: JSON.stringify(requestBody)
193
+ });
194
+ if (!response.ok) {
195
+ const errorText = await response.text();
196
+ throw new Error(`OpenAI API error (${response.status}): ${errorText}`);
197
+ }
198
+ const json = await response.json();
199
+ const output = json.choices[0]?.message?.content ?? "";
200
+ const snapshot = createSnapshot({
201
+ executionId: crypto2.randomUUID(),
202
+ provider: "openai",
203
+ model,
204
+ modelVersion: params.modelVersion ?? json.model ?? null,
205
+ prompt: params.prompt,
206
+ input: params.input,
207
+ parameters: {
208
+ temperature,
209
+ maxTokens,
210
+ topP,
211
+ seed
212
+ },
213
+ output,
214
+ appId: params.appId ?? null
215
+ });
216
+ const bundle = sealCer(snapshot);
217
+ return { output, snapshot, bundle };
218
+ }
219
+ export {
220
+ runOpenAIChatExecution
221
+ };
222
+ //# sourceMappingURL=openai.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hash.ts","../../src/canonicalJson.ts","../../src/snapshot.ts","../../src/cer.ts","../../src/providers/openai.ts"],"sourcesContent":["import * as crypto from 'crypto';\nimport { toCanonicalJson } from './canonicalJson.js';\n\nexport function sha256Hex(data: string | Uint8Array): string {\n const hash = crypto.createHash('sha256');\n if (typeof data === 'string') {\n hash.update(data, 'utf-8');\n } else {\n hash.update(data);\n }\n return hash.digest('hex');\n}\n\nexport function hashUtf8(value: string): string {\n return `sha256:${sha256Hex(value)}`;\n}\n\nexport function hashCanonicalJson(value: unknown): string {\n const canonical = toCanonicalJson(value);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function computeInputHash(input: string | Record<string, unknown>): string {\n if (typeof input === 'string') {\n return hashUtf8(input);\n }\n return hashCanonicalJson(input);\n}\n\nexport function computeOutputHash(output: string | Record<string, unknown>): string {\n if (typeof output === 'string') {\n return hashUtf8(output);\n }\n return hashCanonicalJson(output);\n}\n","export function toCanonicalJson(value: unknown): string {\n return canonicalize(value);\n}\n\nfunction canonicalize(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);\n }\n return JSON.stringify(value);\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n const items = value.map(item => canonicalize(item));\n return '[' + items.join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(key => {\n const val = obj[key];\n if (val === undefined) {\n return null;\n }\n return JSON.stringify(key) + ':' + canonicalize(val);\n }).filter(e => e !== null);\n return '{' + entries.join(',') + '}';\n }\n\n throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);\n}\n","import type { AiExecutionSnapshotV1, CreateSnapshotParams, VerificationResult, AiExecutionParameters } from './types.js';\nimport { computeInputHash, computeOutputHash } from './hash.js';\n\nconst PACKAGE_VERSION = '0.4.0';\n\nfunction validateParameters(params: AiExecutionParameters): string[] {\n const errors: string[] = [];\n\n if (typeof params.temperature !== 'number' || !Number.isFinite(params.temperature)) {\n errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);\n }\n\n if (typeof params.maxTokens !== 'number' || !Number.isFinite(params.maxTokens)) {\n errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);\n }\n\n if (params.topP !== null && (typeof params.topP !== 'number' || !Number.isFinite(params.topP))) {\n errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);\n }\n\n if (params.seed !== null && (typeof params.seed !== 'number' || !Number.isFinite(params.seed))) {\n errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);\n }\n\n return errors;\n}\n\nexport function createSnapshot(params: CreateSnapshotParams): AiExecutionSnapshotV1 {\n const paramErrors = validateParameters(params.parameters);\n if (paramErrors.length > 0) {\n throw new Error(`Invalid parameters: ${paramErrors.join('; ')}`);\n }\n\n const inputHash = computeInputHash(params.input);\n const outputHash = computeOutputHash(params.output);\n\n const snapshot: AiExecutionSnapshotV1 = {\n type: 'ai.execution.v1',\n protocolVersion: '1.2.0',\n executionSurface: 'ai',\n executionId: params.executionId,\n timestamp: params.timestamp ?? new Date().toISOString(),\n provider: params.provider,\n model: params.model,\n modelVersion: params.modelVersion ?? null,\n prompt: params.prompt,\n input: params.input,\n inputHash,\n parameters: {\n temperature: params.parameters.temperature,\n maxTokens: params.parameters.maxTokens,\n topP: params.parameters.topP ?? null,\n seed: params.parameters.seed ?? null,\n },\n output: params.output,\n outputHash,\n sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,\n appId: params.appId ?? null,\n };\n\n if (params.runId !== undefined) snapshot.runId = params.runId ?? null;\n if (params.stepId !== undefined) snapshot.stepId = params.stepId ?? null;\n if (params.stepIndex !== undefined) snapshot.stepIndex = params.stepIndex ?? null;\n if (params.workflowId !== undefined) snapshot.workflowId = params.workflowId ?? null;\n if (params.conversationId !== undefined) snapshot.conversationId = params.conversationId ?? null;\n if (params.prevStepHash !== undefined) snapshot.prevStepHash = params.prevStepHash ?? null;\n\n return snapshot;\n}\n\nexport function verifySnapshot(snapshot: AiExecutionSnapshotV1): VerificationResult {\n const errors: string[] = [];\n\n if (snapshot.type !== 'ai.execution.v1') {\n errors.push(`Expected type \"ai.execution.v1\", got \"${snapshot.type}\"`);\n }\n\n if (snapshot.protocolVersion !== '1.2.0') {\n errors.push(`Expected protocolVersion \"1.2.0\", got \"${snapshot.protocolVersion}\"`);\n }\n\n if (snapshot.executionSurface !== 'ai') {\n errors.push(`Expected executionSurface \"ai\", got \"${snapshot.executionSurface}\"`);\n }\n\n if (!snapshot.executionId || typeof snapshot.executionId !== 'string') {\n errors.push('executionId must be a non-empty string');\n }\n\n if (!snapshot.timestamp || typeof snapshot.timestamp !== 'string') {\n errors.push('timestamp must be a non-empty string');\n }\n\n if (!snapshot.provider || typeof snapshot.provider !== 'string') {\n errors.push('provider must be a non-empty string');\n }\n\n if (!snapshot.model || typeof snapshot.model !== 'string') {\n errors.push('model must be a non-empty string');\n }\n\n if (!snapshot.prompt || typeof snapshot.prompt !== 'string') {\n errors.push('prompt must be a non-empty string');\n }\n\n if (snapshot.input === undefined || snapshot.input === null) {\n errors.push('input must be a string or object');\n }\n\n if (snapshot.output === undefined || snapshot.output === null) {\n errors.push('output must be a string or object');\n }\n\n const paramErrors = validateParameters(snapshot.parameters);\n errors.push(...paramErrors);\n\n if (!snapshot.inputHash || !snapshot.inputHash.startsWith('sha256:')) {\n errors.push(`inputHash must start with \"sha256:\", got \"${snapshot.inputHash}\"`);\n }\n\n if (!snapshot.outputHash || !snapshot.outputHash.startsWith('sha256:')) {\n errors.push(`outputHash must start with \"sha256:\", got \"${snapshot.outputHash}\"`);\n }\n\n const expectedInputHash = computeInputHash(snapshot.input);\n if (snapshot.inputHash !== expectedInputHash) {\n errors.push(`inputHash mismatch: expected ${expectedInputHash}, got ${snapshot.inputHash}`);\n }\n\n const expectedOutputHash = computeOutputHash(snapshot.output);\n if (snapshot.outputHash !== expectedOutputHash) {\n errors.push(`outputHash mismatch: expected ${expectedOutputHash}, got ${snapshot.outputHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import type { AiExecutionSnapshotV1, CerAiExecutionBundle, CerMeta, VerificationResult } from './types.js';\nimport { toCanonicalJson } from './canonicalJson.js';\nimport { sha256Hex } from './hash.js';\nimport { verifySnapshot } from './snapshot.js';\n\ninterface CertificatePayload {\n bundleType: 'cer.ai.execution.v1';\n createdAt: string;\n snapshot: AiExecutionSnapshotV1;\n version: '0.1';\n}\n\nfunction computeCertificateHash(payload: CertificatePayload): string {\n const canonical = toCanonicalJson(payload);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function sealCer(\n snapshot: AiExecutionSnapshotV1,\n options?: { createdAt?: string; meta?: CerMeta }\n): CerAiExecutionBundle {\n const createdAt = options?.createdAt ?? new Date().toISOString();\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt,\n snapshot,\n version: '0.1',\n };\n\n const certificateHash = computeCertificateHash(payload);\n\n const bundle: CerAiExecutionBundle = {\n bundleType: 'cer.ai.execution.v1',\n certificateHash,\n createdAt,\n version: '0.1',\n snapshot,\n };\n\n if (options?.meta) {\n bundle.meta = options.meta;\n }\n\n return bundle;\n}\n\nexport function verifyCer(bundle: CerAiExecutionBundle): VerificationResult {\n const errors: string[] = [];\n\n if (bundle.bundleType !== 'cer.ai.execution.v1') {\n errors.push(`Expected bundleType \"cer.ai.execution.v1\", got \"${bundle.bundleType}\"`);\n }\n\n if (bundle.version !== '0.1') {\n errors.push(`Expected version \"0.1\", got \"${bundle.version}\"`);\n }\n\n if (!bundle.createdAt || typeof bundle.createdAt !== 'string') {\n errors.push('createdAt must be a non-empty string');\n }\n\n if (!bundle.certificateHash || !bundle.certificateHash.startsWith('sha256:')) {\n errors.push(`certificateHash must start with \"sha256:\", got \"${bundle.certificateHash}\"`);\n }\n\n if (!bundle.snapshot) {\n errors.push('snapshot is required');\n return { ok: false, errors };\n }\n\n const snapshotResult = verifySnapshot(bundle.snapshot);\n errors.push(...snapshotResult.errors);\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt: bundle.createdAt,\n snapshot: bundle.snapshot,\n version: '0.1',\n };\n\n const expectedHash = computeCertificateHash(payload);\n if (bundle.certificateHash !== expectedHash) {\n errors.push(`certificateHash mismatch: expected ${expectedHash}, got ${bundle.certificateHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import type { AiExecutionSnapshotV1, CerAiExecutionBundle } from '../types.js';\nimport { createSnapshot } from '../snapshot.js';\nimport { sealCer } from '../cer.js';\nimport * as crypto from 'crypto';\n\nexport interface OpenAIChatParams {\n prompt: string;\n input: string;\n model?: string;\n modelVersion?: string | null;\n parameters?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number | null;\n seed?: number | null;\n };\n appId?: string | null;\n apiKey?: string;\n}\n\nexport interface OpenAIChatResult {\n output: string;\n snapshot: AiExecutionSnapshotV1;\n bundle: CerAiExecutionBundle;\n}\n\nexport async function runOpenAIChatExecution(params: OpenAIChatParams): Promise<OpenAIChatResult> {\n const apiKey = params.apiKey || process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'Missing OpenAI API key. Set OPENAI_API_KEY environment variable or pass apiKey in params.'\n );\n }\n\n const model = params.model ?? 'gpt-4o';\n const temperature = params.parameters?.temperature ?? 0.7;\n const maxTokens = params.parameters?.maxTokens ?? 1024;\n const topP = params.parameters?.topP ?? null;\n const seed = params.parameters?.seed ?? null;\n\n const requestBody: Record<string, unknown> = {\n model,\n messages: [\n { role: 'system', content: params.prompt },\n { role: 'user', content: params.input },\n ],\n temperature,\n max_tokens: maxTokens,\n };\n\n if (topP !== null) {\n requestBody.top_p = topP;\n }\n if (seed !== null) {\n requestBody.seed = seed;\n }\n\n const response = await fetch('https://api.openai.com/v1/chat/completions', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`OpenAI API error (${response.status}): ${errorText}`);\n }\n\n const json = await response.json() as {\n choices: Array<{ message: { content: string } }>;\n model: string;\n };\n\n const output = json.choices[0]?.message?.content ?? '';\n\n const snapshot = createSnapshot({\n executionId: crypto.randomUUID(),\n provider: 'openai',\n model,\n modelVersion: params.modelVersion ?? json.model ?? null,\n prompt: params.prompt,\n input: params.input,\n parameters: {\n temperature,\n maxTokens,\n topP,\n seed,\n },\n output,\n appId: params.appId ?? null,\n });\n\n const bundle = sealCer(snapshot);\n\n return { output, snapshot, bundle };\n}\n"],"mappings":"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","names":["crypto"]}