langwatch 0.8.2 → 0.10.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 (70) hide show
  1. package/dist/{add-EY2WXUSP.mjs → add-5FRWEQ32.mjs} +5 -5
  2. package/dist/{add-GEM46CRC.js → add-CXUS4ZSQ.js} +8 -8
  3. package/dist/{add-GEM46CRC.js.map → add-CXUS4ZSQ.js.map} +1 -1
  4. package/dist/{chunk-BP2WGNIV.js → chunk-A43BYF5Q.js} +6 -2
  5. package/dist/chunk-A43BYF5Q.js.map +1 -0
  6. package/dist/{chunk-KLVHQVMF.js → chunk-BTCJWUS5.js} +14 -14
  7. package/dist/{chunk-KLVHQVMF.js.map → chunk-BTCJWUS5.js.map} +1 -1
  8. package/dist/{chunk-PLCZYSRL.mjs → chunk-I3X7VMSP.mjs} +136 -60
  9. package/dist/chunk-I3X7VMSP.mjs.map +1 -0
  10. package/dist/{chunk-SRI6HEGF.js → chunk-NM5OKM7F.js} +142 -66
  11. package/dist/chunk-NM5OKM7F.js.map +1 -0
  12. package/dist/{chunk-VJV532JA.mjs → chunk-VGVWXKVM.mjs} +2 -2
  13. package/dist/{chunk-GNKQTK4I.mjs → chunk-W6FD5ZO3.mjs} +2 -2
  14. package/dist/chunk-W6FD5ZO3.mjs.map +1 -0
  15. package/dist/{chunk-DQU2PZAL.mjs → chunk-WHPBZSTS.mjs} +6 -2
  16. package/dist/chunk-WHPBZSTS.mjs.map +1 -0
  17. package/dist/{chunk-ZNWSX2QV.js → chunk-YWO3NE5A.js} +2 -2
  18. package/dist/chunk-YWO3NE5A.js.map +1 -0
  19. package/dist/cli/index.js +6 -6
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/cli/index.mjs +6 -6
  22. package/dist/cli/index.mjs.map +1 -1
  23. package/dist/{implementation-TF91Gn0l.d.ts → implementation-CPxv2BdW.d.ts} +1 -1
  24. package/dist/{implementation-pq0g2B5y.d.mts → implementation-CVrmD0bz.d.mts} +1 -1
  25. package/dist/index.d.mts +42 -31
  26. package/dist/index.d.ts +42 -31
  27. package/dist/index.js +14 -12
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +8 -6
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{list-GCZWLGUG.mjs → list-DQ6XLQCK.mjs} +5 -5
  32. package/dist/{list-DRJJH66J.js → list-K6E3OGYH.js} +8 -8
  33. package/dist/{list-DRJJH66J.js.map → list-K6E3OGYH.js.map} +1 -1
  34. package/dist/{login-S4O6A5OF.js → login-HX7WMLPL.js} +3 -3
  35. package/dist/{login-S4O6A5OF.js.map → login-HX7WMLPL.js.map} +1 -1
  36. package/dist/{login-WHSTC3WT.mjs → login-TJ2NCUAJ.mjs} +2 -2
  37. package/dist/observability-sdk/index.d.mts +3 -3
  38. package/dist/observability-sdk/index.d.ts +3 -3
  39. package/dist/observability-sdk/index.js +4 -4
  40. package/dist/observability-sdk/index.js.map +1 -1
  41. package/dist/observability-sdk/index.mjs +8 -8
  42. package/dist/observability-sdk/instrumentation/langchain/index.d.mts +1 -1
  43. package/dist/observability-sdk/instrumentation/langchain/index.d.ts +1 -1
  44. package/dist/observability-sdk/instrumentation/langchain/index.js +3 -3
  45. package/dist/observability-sdk/instrumentation/langchain/index.mjs +1 -1
  46. package/dist/observability-sdk/setup/node/index.js +11 -11
  47. package/dist/observability-sdk/setup/node/index.js.map +1 -1
  48. package/dist/observability-sdk/setup/node/index.mjs +3 -3
  49. package/dist/observability-sdk/setup/node/index.mjs.map +1 -1
  50. package/dist/{remove-LBVMOEMQ.js → remove-45A7WUCB.js} +7 -7
  51. package/dist/{remove-LBVMOEMQ.js.map → remove-45A7WUCB.js.map} +1 -1
  52. package/dist/{remove-TISUKAUX.mjs → remove-5ZOYQTF4.mjs} +5 -5
  53. package/dist/{sync-SIHBU67A.js → sync-BE7XZC2A.js} +7 -7
  54. package/dist/{sync-SIHBU67A.js.map → sync-BE7XZC2A.js.map} +1 -1
  55. package/dist/{sync-QYFJZVU7.mjs → sync-LL6TTFMS.mjs} +5 -5
  56. package/dist/{types-DhEYjnRD.d.mts → types-Kts5RGLY.d.mts} +15 -1
  57. package/dist/{types-CAQOMGrf.d.ts → types-usU5mTCX.d.ts} +15 -1
  58. package/package.json +142 -124
  59. package/dist/chunk-BP2WGNIV.js.map +0 -1
  60. package/dist/chunk-DQU2PZAL.mjs.map +0 -1
  61. package/dist/chunk-GNKQTK4I.mjs.map +0 -1
  62. package/dist/chunk-PLCZYSRL.mjs.map +0 -1
  63. package/dist/chunk-SRI6HEGF.js.map +0 -1
  64. package/dist/chunk-ZNWSX2QV.js.map +0 -1
  65. /package/dist/{add-EY2WXUSP.mjs.map → add-5FRWEQ32.mjs.map} +0 -0
  66. /package/dist/{chunk-VJV532JA.mjs.map → chunk-VGVWXKVM.mjs.map} +0 -0
  67. /package/dist/{list-GCZWLGUG.mjs.map → list-DQ6XLQCK.mjs.map} +0 -0
  68. /package/dist/{login-WHSTC3WT.mjs.map → login-TJ2NCUAJ.mjs.map} +0 -0
  69. /package/dist/{remove-TISUKAUX.mjs.map → remove-5ZOYQTF4.mjs.map} +0 -0
  70. /package/dist/{sync-QYFJZVU7.mjs.map → sync-LL6TTFMS.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/langwatch/langwatch/typescript-sdk/dist/sync-SIHBU67A.js","../src/cli/commands/sync.ts"],"names":[],"mappings":"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","file":"/home/runner/work/langwatch/langwatch/typescript-sdk/dist/sync-SIHBU67A.js","sourcesContent":[null,"import * as fs from \"fs\";\nimport * as path from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport * as yaml from \"js-yaml\";\nimport { PromptConverter } from \"@/cli/utils/promptConverter\";\nimport {\n type ConfigData,\n PromptsApiService,\n PromptsError,\n type SyncAction,\n} from \"@/client-sdk/services/prompts\";\nimport type { SyncResult } from \"../types\";\nimport { FileManager } from \"../utils/fileManager\";\nimport { ensureProjectInitialized } from \"../utils/init\";\nimport { checkApiKey } from \"../utils/apiKey\";\nimport readline from \"node:readline\";\n\n// Handle conflict resolution - show diff and ask user to choose\nconst handleConflict = async (\n promptName: string,\n conflictInfo: {\n localVersion: number;\n remoteVersion: number;\n differences: string[];\n remoteConfigData: any;\n }\n): Promise<\"local\" | \"remote\" | \"abort\"> => {\n console.log(\n chalk.yellow(`\\n⚠ Conflict detected for prompt: ${chalk.cyan(promptName)}`)\n );\n console.log(\n chalk.gray(\n `Local version: ${conflictInfo.localVersion}, Remote version: ${conflictInfo.remoteVersion}`\n )\n );\n\n if (conflictInfo.differences.length > 0) {\n console.log(chalk.yellow(\"\\nDifferences:\"));\n conflictInfo.differences.forEach((diff) => {\n console.log(chalk.gray(` • ${diff}`));\n });\n }\n\n console.log(chalk.yellow(\"\\nOptions:\"));\n console.log(\" [l] Use local version (overwrite remote)\");\n console.log(\" [r] Use remote version (overwrite local)\");\n console.log(\" [a] Abort sync for this prompt\");\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(\"Choose resolution (l/r/a): \", (answer: string) => {\n rl.close();\n const choice = answer.toLowerCase();\n if (choice === \"l\" || choice === \"local\") {\n resolve(\"local\");\n } else if (choice === \"r\" || choice === \"remote\") {\n resolve(\"remote\");\n } else {\n resolve(\"abort\");\n }\n });\n });\n};\n\nexport const syncCommand = async (): Promise<void> => {\n console.log(\"🔄 Starting sync...\");\n\n const startTime = Date.now();\n\n try {\n // Check API key before doing anything else\n checkApiKey();\n\n // Get prompts API service\n const promptsApiService = new PromptsApiService();\n\n // Ensure project is initialized (prompts.json, lock file, directories)\n await ensureProjectInitialized(false); // Don't prompt for .gitignore in sync\n\n // Load prompts config and lock\n const config = FileManager.loadPromptsConfig();\n const lock = FileManager.loadPromptsLock();\n\n const result: SyncResult = {\n fetched: [],\n pushed: [],\n unchanged: [],\n cleaned: [],\n errors: [],\n };\n\n // Process remote prompts (fetch and materialize)\n const remoteDeps = Object.entries(config.prompts).filter(\n ([, dependency]) => {\n // Skip local file dependencies (both object format and string format)\n if (typeof dependency === \"object\" && dependency.file) {\n return false;\n }\n if (typeof dependency === \"string\" && dependency.startsWith(\"file:\")) {\n return false;\n }\n return true;\n }\n );\n\n if (remoteDeps.length > 0) {\n const fetchSpinner = ora(\n `Checking ${remoteDeps.length} remote prompts...`\n ).start();\n\n for (const [name, dependency] of remoteDeps) {\n try {\n const versionSpec =\n typeof dependency === \"string\"\n ? dependency\n : dependency.version ?? \"latest\";\n\n // Check if we already have this prompt with the same version\n const lockEntry = lock.prompts[name];\n\n // Fetch the prompt from the API to check current version\n const prompt = await promptsApiService.get(name);\n\n if (prompt) {\n // Check if we need to update (new version or not materialized)\n const needsUpdate =\n !lockEntry ||\n lockEntry.version !== prompt.version ||\n !lockEntry.materialized ||\n !fs.existsSync(path.resolve(lockEntry.materialized));\n\n if (needsUpdate) {\n // Convert to MaterializedPrompt format using the converter\n const materializedPrompt =\n PromptConverter.fromApiToMaterialized(prompt);\n\n const savedPath = FileManager.saveMaterializedPrompt(\n name,\n materializedPrompt\n );\n const relativePath = path.relative(process.cwd(), savedPath);\n result.fetched.push({\n name,\n version: prompt.version,\n versionSpec,\n });\n\n // Update lock file entry\n FileManager.updateLockEntry(\n lock,\n name,\n materializedPrompt,\n savedPath\n );\n\n fetchSpinner.text = `Fetched ${chalk.cyan(\n `${name}@${versionSpec}`\n )} ${chalk.gray(`(version ${prompt.version})`)} → ${chalk.gray(\n relativePath\n )}`;\n } else {\n // No change needed, track as unchanged\n result.unchanged.push(name);\n }\n } else {\n result.errors.push({ name, error: \"Prompt not found\" });\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n result.errors.push({ name, error: errorMessage });\n }\n }\n\n fetchSpinner.stop();\n }\n\n // Process local prompts (push to API) - only those explicitly declared in prompts.json\n const localFileRefs = Object.entries(config.prompts).filter(\n ([, dependency]) => {\n return typeof dependency === \"string\" && dependency.startsWith(\"file:\");\n }\n );\n\n if (localFileRefs.length > 0) {\n const pushSpinner = ora(\n `Pushing ${localFileRefs.length} local prompts...`\n ).start();\n\n // Use the existing lock file instead of reloading it\n // const lock = FileManager.loadPromptsLock(); // Don't reload - use existing lock\n\n for (const [promptName, dependency] of localFileRefs) {\n try {\n const filePath = (dependency as string).slice(5); // Remove \"file:\" prefix\n\n // Load local prompt config\n const localConfig = FileManager.loadLocalPrompt(filePath);\n\n // Get current version from lock file\n const currentVersion = lock.prompts[promptName]?.version;\n\n // Convert local config to API configData format\n const configData: ConfigData = {\n model: localConfig.model,\n prompt: PromptConverter.extractSystemPrompt(localConfig.messages),\n messages: PromptConverter.filterNonSystemMessages(\n localConfig.messages\n ) as Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n }>,\n temperature: localConfig.modelParameters?.temperature,\n max_tokens: localConfig.modelParameters?.max_tokens,\n inputs: [{ identifier: \"input\", type: \"str\" }],\n outputs: [{ identifier: \"output\", type: \"str\" }],\n };\n\n // Use new sync API with conflict detection\n const syncResult = await promptsApiService.sync({\n name: promptName,\n configData,\n localVersion: currentVersion,\n commitMessage: `Synced from local file: ${path.basename(filePath)}`,\n });\n\n const relativePath = path.relative(process.cwd(), filePath);\n\n let conflictResolution: \"local\" | \"remote\" | \"abort\" | null = null;\n if (syncResult.action === \"conflict\") {\n // Handle conflict - prompt user for resolution\n pushSpinner.stop();\n conflictResolution = await handleConflict(\n promptName,\n syncResult.conflictInfo!\n );\n if (conflictResolution === \"abort\") {\n result.errors.push({\n name: promptName,\n error: \"Sync aborted due to conflict\",\n });\n continue;\n }\n\n // If user chose remote, we should pull the remote version to local file\n if (conflictResolution === \"remote\" && syncResult.conflictInfo) {\n // Update local file with remote content\n const remoteConfig = {\n model: syncResult.conflictInfo.remoteConfigData.model,\n modelParameters: {\n temperature:\n syncResult.conflictInfo.remoteConfigData.temperature,\n max_tokens:\n syncResult.conflictInfo.remoteConfigData.max_tokens,\n },\n messages: [\n {\n role: \"system\" as const,\n content: syncResult.conflictInfo.remoteConfigData.prompt,\n },\n ...(syncResult.conflictInfo.remoteConfigData.messages ?? []),\n ],\n };\n\n const yamlContent = yaml.dump(remoteConfig, {\n lineWidth: -1,\n noRefs: true,\n sortKeys: false,\n });\n\n fs.writeFileSync(filePath, yamlContent);\n }\n\n // If user chose to proceed, we continue with the sync\n pushSpinner.start();\n }\n\n // Update lock file with new version info\n if (syncResult.prompt) {\n lock.prompts[promptName] = {\n version: syncResult.prompt.version,\n versionId: syncResult.prompt.versionId,\n materialized: filePath,\n };\n } else if (syncResult.action === \"conflict\") {\n const remoteVersion = syncResult.conflictInfo?.remoteVersion ?? 0;\n if (conflictResolution === \"remote\") {\n // User chose remote - use remote version\n lock.prompts[promptName] = {\n version: remoteVersion,\n versionId: \"remote_version\", // We don't have the actual versionId from conflict info\n materialized: filePath,\n };\n } else {\n // User chose local - force push\n const formattedConfig = PromptConverter.fromLocalToApiFormat(localConfig);\n const updatedPrompt = await promptsApiService.update(promptName, {\n ...formattedConfig,\n commitMessage: `Updated via CLI: synced from local file`\n });\n lock.prompts[promptName] = {\n version: updatedPrompt.version,\n versionId: updatedPrompt.versionId,\n materialized: filePath,\n };\n }\n }\n\n // Determine the action text based on sync result and conflict resolution\n let actionText: string;\n if (syncResult.action === \"conflict\") {\n if (conflictResolution === \"remote\") {\n actionText = \"Pulled\"; // User chose to use remote version\n result.fetched.push({\n name: promptName,\n version: syncResult.conflictInfo?.remoteVersion ?? 0,\n versionSpec: \"latest\", // Default for conflict resolution\n });\n } else {\n actionText = \"Pushed\"; // User chose to use local version (or forced push)\n result.pushed.push({\n name: promptName,\n version: (syncResult.conflictInfo?.remoteVersion ?? 0) + 1, // New version after push\n });\n }\n } else if (syncResult.action === \"up_to_date\") {\n // For up-to-date prompts, add to unchanged instead of pushed\n actionText = \"Up-to-date\";\n result.unchanged.push(promptName);\n } else {\n const actionMap: Record<SyncAction, string> = {\n created: \"Created\",\n updated: \"Updated\",\n conflict: \"Conflict resolved\",\n up_to_date: \"Up to date\",\n };\n actionText = actionMap[syncResult.action as SyncAction] || \"Pushed\";\n result.pushed.push({\n name: promptName,\n version: syncResult.prompt?.version ?? 0,\n });\n }\n\n pushSpinner.text = `${actionText} ${chalk.cyan(\n promptName\n )} ${chalk.gray(\n `(version ${\n syncResult.prompt?.version ??\n syncResult.conflictInfo?.remoteVersion ??\n \"unknown\"\n })`\n )} ${conflictResolution === \"remote\" ? \"to\" : \"from\"} ${chalk.gray(\n relativePath\n )}`;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n result.errors.push({ name: promptName, error: errorMessage });\n }\n }\n\n // Save lock file with all updates\n FileManager.savePromptsLock(lock);\n\n pushSpinner.stop();\n }\n\n // Check for orphan local prompt files and show helpful warnings\n const discoveredLocalFiles = FileManager.getLocalPromptFiles();\n const orphanFiles = discoveredLocalFiles.filter((filePath) => {\n const promptName = FileManager.promptNameFromPath(filePath);\n return !config.prompts[promptName]; // Not declared in prompts.json\n });\n\n if (orphanFiles.length > 0) {\n console.log(\n chalk.yellow(\n `\\n⚠ Found ${orphanFiles.length} orphan prompt file${\n orphanFiles.length > 1 ? \"s\" : \"\"\n }:`\n )\n );\n\n for (const filePath of orphanFiles) {\n const promptName = FileManager.promptNameFromPath(filePath);\n const relativePath = path.relative(process.cwd(), filePath);\n\n console.log(chalk.yellow(` ${relativePath}`));\n console.log(\n chalk.gray(\n ` Add to prompts.json: \"${promptName}\": \"file:${relativePath}\"`\n )\n );\n }\n\n console.log(\n chalk.gray(\n `\\nTip: Add these to prompts.json to include them in sync operations.`\n )\n );\n }\n\n // Cleanup orphaned materialized files\n const currentDependencies = new Set(\n Object.keys(config.prompts).filter((name) => {\n const dependency = config.prompts[name];\n // Only include remote dependencies (not local file: dependencies)\n if (typeof dependency === \"object\" && dependency.file) {\n return false;\n }\n if (typeof dependency === \"string\" && dependency.startsWith(\"file:\")) {\n return false;\n }\n return true;\n })\n );\n\n const cleanedFiles =\n FileManager.cleanupOrphanedMaterializedFiles(currentDependencies);\n if (cleanedFiles.length > 0) {\n result.cleaned = cleanedFiles;\n FileManager.removeFromLock(lock, cleanedFiles);\n }\n\n // Save the updated lock file\n FileManager.savePromptsLock(lock);\n\n // Print individual results if there were actions\n if (result.fetched.length > 0) {\n for (const { name, version, versionSpec } of result.fetched) {\n // Get the actual saved path from lock file for display consistency\n const lockEntry = lock.prompts[name];\n const displayPath = lockEntry?.materialized\n ? `./${lockEntry.materialized}`\n : `./prompts/.materialized/${name}.prompt.yaml`;\n\n console.log(\n chalk.green(\n `✓ Pulled ${chalk.cyan(`${name}@${versionSpec}`)} ${chalk.gray(\n `(version ${version})`\n )} → ${chalk.gray(displayPath)}`\n )\n );\n }\n }\n\n if (result.pushed.length > 0) {\n for (const { name, version } of result.pushed) {\n const localPath = `./prompts/${name}.prompt.yaml`;\n console.log(\n chalk.green(\n `✓ Pushed ${chalk.cyan(name)} ${chalk.gray(\n `(version ${version})`\n )} from ${chalk.gray(localPath)}`\n )\n );\n }\n }\n\n // Print cleaned up files\n if (result.cleaned.length > 0) {\n for (const name of result.cleaned) {\n console.log(\n chalk.yellow(\n `✓ Cleaned ${chalk.cyan(name)} (no longer in dependencies)`\n )\n );\n }\n }\n\n // Print errors\n if (result.errors.length > 0) {\n for (const { name, error } of result.errors) {\n console.log(chalk.red(`✗ Failed ${chalk.cyan(name)}: ${error}`));\n }\n }\n\n // Print summary\n const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n const totalActions =\n result.fetched.length + result.pushed.length + result.cleaned.length;\n\n if (totalActions === 0 && result.errors.length === 0) {\n console.log(chalk.gray(`Synced in ${duration}s, no changes`));\n } else {\n const summary = [];\n if (result.fetched.length > 0)\n summary.push(`${result.fetched.length} fetched`);\n if (result.pushed.length > 0)\n summary.push(`${result.pushed.length} pushed`);\n if (result.cleaned.length > 0)\n summary.push(`${result.cleaned.length} cleaned`);\n if (result.errors.length > 0)\n summary.push(`${result.errors.length} errors`);\n\n console.log(chalk.gray(`Synced ${summary.join(\", \")} in ${duration}s`));\n }\n\n if (result.errors.length > 0) {\n process.exit(1);\n }\n } catch (error) {\n if (error instanceof PromptsError) {\n console.error(chalk.red(`Error: ${error.message}`));\n } else {\n console.error(\n chalk.red(\n `Unexpected error: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`\n )\n );\n }\n process.exit(1);\n }\n};\n"]}
1
+ {"version":3,"sources":["/home/runner/work/langwatch/langwatch/typescript-sdk/dist/sync-BE7XZC2A.js","../src/cli/commands/sync.ts"],"names":[],"mappings":"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","file":"/home/runner/work/langwatch/langwatch/typescript-sdk/dist/sync-BE7XZC2A.js","sourcesContent":[null,"import * as fs from \"fs\";\nimport * as path from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport * as yaml from \"js-yaml\";\nimport { PromptConverter } from \"@/cli/utils/promptConverter\";\nimport {\n type ConfigData,\n PromptsApiService,\n PromptsError,\n type SyncAction,\n} from \"@/client-sdk/services/prompts\";\nimport type { SyncResult } from \"../types\";\nimport { FileManager } from \"../utils/fileManager\";\nimport { ensureProjectInitialized } from \"../utils/init\";\nimport { checkApiKey } from \"../utils/apiKey\";\nimport readline from \"node:readline\";\n\n// Handle conflict resolution - show diff and ask user to choose\nconst handleConflict = async (\n promptName: string,\n conflictInfo: {\n localVersion: number;\n remoteVersion: number;\n differences: string[];\n remoteConfigData: any;\n }\n): Promise<\"local\" | \"remote\" | \"abort\"> => {\n console.log(\n chalk.yellow(`\\n⚠ Conflict detected for prompt: ${chalk.cyan(promptName)}`)\n );\n console.log(\n chalk.gray(\n `Local version: ${conflictInfo.localVersion}, Remote version: ${conflictInfo.remoteVersion}`\n )\n );\n\n if (conflictInfo.differences.length > 0) {\n console.log(chalk.yellow(\"\\nDifferences:\"));\n conflictInfo.differences.forEach((diff) => {\n console.log(chalk.gray(` • ${diff}`));\n });\n }\n\n console.log(chalk.yellow(\"\\nOptions:\"));\n console.log(\" [l] Use local version (overwrite remote)\");\n console.log(\" [r] Use remote version (overwrite local)\");\n console.log(\" [a] Abort sync for this prompt\");\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(\"Choose resolution (l/r/a): \", (answer: string) => {\n rl.close();\n const choice = answer.toLowerCase();\n if (choice === \"l\" || choice === \"local\") {\n resolve(\"local\");\n } else if (choice === \"r\" || choice === \"remote\") {\n resolve(\"remote\");\n } else {\n resolve(\"abort\");\n }\n });\n });\n};\n\nexport const syncCommand = async (): Promise<void> => {\n console.log(\"🔄 Starting sync...\");\n\n const startTime = Date.now();\n\n try {\n // Check API key before doing anything else\n checkApiKey();\n\n // Get prompts API service\n const promptsApiService = new PromptsApiService();\n\n // Ensure project is initialized (prompts.json, lock file, directories)\n await ensureProjectInitialized(false); // Don't prompt for .gitignore in sync\n\n // Load prompts config and lock\n const config = FileManager.loadPromptsConfig();\n const lock = FileManager.loadPromptsLock();\n\n const result: SyncResult = {\n fetched: [],\n pushed: [],\n unchanged: [],\n cleaned: [],\n errors: [],\n };\n\n // Process remote prompts (fetch and materialize)\n const remoteDeps = Object.entries(config.prompts).filter(\n ([, dependency]) => {\n // Skip local file dependencies (both object format and string format)\n if (typeof dependency === \"object\" && dependency.file) {\n return false;\n }\n if (typeof dependency === \"string\" && dependency.startsWith(\"file:\")) {\n return false;\n }\n return true;\n }\n );\n\n if (remoteDeps.length > 0) {\n const fetchSpinner = ora(\n `Checking ${remoteDeps.length} remote prompts...`\n ).start();\n\n for (const [name, dependency] of remoteDeps) {\n try {\n const versionSpec =\n typeof dependency === \"string\"\n ? dependency\n : dependency.version ?? \"latest\";\n\n // Check if we already have this prompt with the same version\n const lockEntry = lock.prompts[name];\n\n // Fetch the prompt from the API to check current version\n const prompt = await promptsApiService.get(name);\n\n if (prompt) {\n // Check if we need to update (new version or not materialized)\n const needsUpdate =\n !lockEntry ||\n lockEntry.version !== prompt.version ||\n !lockEntry.materialized ||\n !fs.existsSync(path.resolve(lockEntry.materialized));\n\n if (needsUpdate) {\n // Convert to MaterializedPrompt format using the converter\n const materializedPrompt =\n PromptConverter.fromApiToMaterialized(prompt);\n\n const savedPath = FileManager.saveMaterializedPrompt(\n name,\n materializedPrompt\n );\n const relativePath = path.relative(process.cwd(), savedPath);\n result.fetched.push({\n name,\n version: prompt.version,\n versionSpec,\n });\n\n // Update lock file entry\n FileManager.updateLockEntry(\n lock,\n name,\n materializedPrompt,\n savedPath\n );\n\n fetchSpinner.text = `Fetched ${chalk.cyan(\n `${name}@${versionSpec}`\n )} ${chalk.gray(`(version ${prompt.version})`)} → ${chalk.gray(\n relativePath\n )}`;\n } else {\n // No change needed, track as unchanged\n result.unchanged.push(name);\n }\n } else {\n result.errors.push({ name, error: \"Prompt not found\" });\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n result.errors.push({ name, error: errorMessage });\n }\n }\n\n fetchSpinner.stop();\n }\n\n // Process local prompts (push to API) - only those explicitly declared in prompts.json\n const localFileRefs = Object.entries(config.prompts).filter(\n ([, dependency]) => {\n return typeof dependency === \"string\" && dependency.startsWith(\"file:\");\n }\n );\n\n if (localFileRefs.length > 0) {\n const pushSpinner = ora(\n `Pushing ${localFileRefs.length} local prompts...`\n ).start();\n\n // Use the existing lock file instead of reloading it\n // const lock = FileManager.loadPromptsLock(); // Don't reload - use existing lock\n\n for (const [promptName, dependency] of localFileRefs) {\n try {\n const filePath = (dependency as string).slice(5); // Remove \"file:\" prefix\n\n // Load local prompt config\n const localConfig = FileManager.loadLocalPrompt(filePath);\n\n // Get current version from lock file\n const currentVersion = lock.prompts[promptName]?.version;\n\n // Convert local config to API configData format\n const configData: ConfigData = {\n model: localConfig.model,\n prompt: PromptConverter.extractSystemPrompt(localConfig.messages),\n messages: PromptConverter.filterNonSystemMessages(\n localConfig.messages\n ) as Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n }>,\n temperature: localConfig.modelParameters?.temperature,\n max_tokens: localConfig.modelParameters?.max_tokens,\n inputs: [{ identifier: \"input\", type: \"str\" }],\n outputs: [{ identifier: \"output\", type: \"str\" }],\n };\n\n // Use new sync API with conflict detection\n const syncResult = await promptsApiService.sync({\n name: promptName,\n configData,\n localVersion: currentVersion,\n commitMessage: `Synced from local file: ${path.basename(filePath)}`,\n });\n\n const relativePath = path.relative(process.cwd(), filePath);\n\n let conflictResolution: \"local\" | \"remote\" | \"abort\" | null = null;\n if (syncResult.action === \"conflict\") {\n // Handle conflict - prompt user for resolution\n pushSpinner.stop();\n conflictResolution = await handleConflict(\n promptName,\n syncResult.conflictInfo!\n );\n if (conflictResolution === \"abort\") {\n result.errors.push({\n name: promptName,\n error: \"Sync aborted due to conflict\",\n });\n continue;\n }\n\n // If user chose remote, we should pull the remote version to local file\n if (conflictResolution === \"remote\" && syncResult.conflictInfo) {\n // Update local file with remote content\n const remoteConfig = {\n model: syncResult.conflictInfo.remoteConfigData.model,\n modelParameters: {\n temperature:\n syncResult.conflictInfo.remoteConfigData.temperature,\n max_tokens:\n syncResult.conflictInfo.remoteConfigData.max_tokens,\n },\n messages: [\n {\n role: \"system\" as const,\n content: syncResult.conflictInfo.remoteConfigData.prompt,\n },\n ...(syncResult.conflictInfo.remoteConfigData.messages ?? []),\n ],\n };\n\n const yamlContent = yaml.dump(remoteConfig, {\n lineWidth: -1,\n noRefs: true,\n sortKeys: false,\n });\n\n fs.writeFileSync(filePath, yamlContent);\n }\n\n // If user chose to proceed, we continue with the sync\n pushSpinner.start();\n }\n\n // Update lock file with new version info\n if (syncResult.prompt) {\n lock.prompts[promptName] = {\n version: syncResult.prompt.version,\n versionId: syncResult.prompt.versionId,\n materialized: filePath,\n };\n } else if (syncResult.action === \"conflict\") {\n const remoteVersion = syncResult.conflictInfo?.remoteVersion ?? 0;\n if (conflictResolution === \"remote\") {\n // User chose remote - use remote version\n lock.prompts[promptName] = {\n version: remoteVersion,\n versionId: \"remote_version\", // We don't have the actual versionId from conflict info\n materialized: filePath,\n };\n } else {\n // User chose local - force push\n const formattedConfig = PromptConverter.fromLocalToApiFormat(localConfig);\n const updatedPrompt = await promptsApiService.update(promptName, {\n ...formattedConfig,\n commitMessage: `Updated via CLI: synced from local file`\n });\n lock.prompts[promptName] = {\n version: updatedPrompt.version,\n versionId: updatedPrompt.versionId,\n materialized: filePath,\n };\n }\n }\n\n // Determine the action text based on sync result and conflict resolution\n let actionText: string;\n if (syncResult.action === \"conflict\") {\n if (conflictResolution === \"remote\") {\n actionText = \"Pulled\"; // User chose to use remote version\n result.fetched.push({\n name: promptName,\n version: syncResult.conflictInfo?.remoteVersion ?? 0,\n versionSpec: \"latest\", // Default for conflict resolution\n });\n } else {\n actionText = \"Pushed\"; // User chose to use local version (or forced push)\n result.pushed.push({\n name: promptName,\n version: (syncResult.conflictInfo?.remoteVersion ?? 0) + 1, // New version after push\n });\n }\n } else if (syncResult.action === \"up_to_date\") {\n // For up-to-date prompts, add to unchanged instead of pushed\n actionText = \"Up-to-date\";\n result.unchanged.push(promptName);\n } else {\n const actionMap: Record<SyncAction, string> = {\n created: \"Created\",\n updated: \"Updated\",\n conflict: \"Conflict resolved\",\n up_to_date: \"Up to date\",\n };\n actionText = actionMap[syncResult.action as SyncAction] || \"Pushed\";\n result.pushed.push({\n name: promptName,\n version: syncResult.prompt?.version ?? 0,\n });\n }\n\n pushSpinner.text = `${actionText} ${chalk.cyan(\n promptName\n )} ${chalk.gray(\n `(version ${\n syncResult.prompt?.version ??\n syncResult.conflictInfo?.remoteVersion ??\n \"unknown\"\n })`\n )} ${conflictResolution === \"remote\" ? \"to\" : \"from\"} ${chalk.gray(\n relativePath\n )}`;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n result.errors.push({ name: promptName, error: errorMessage });\n }\n }\n\n // Save lock file with all updates\n FileManager.savePromptsLock(lock);\n\n pushSpinner.stop();\n }\n\n // Check for orphan local prompt files and show helpful warnings\n const discoveredLocalFiles = FileManager.getLocalPromptFiles();\n const orphanFiles = discoveredLocalFiles.filter((filePath) => {\n const promptName = FileManager.promptNameFromPath(filePath);\n return !config.prompts[promptName]; // Not declared in prompts.json\n });\n\n if (orphanFiles.length > 0) {\n console.log(\n chalk.yellow(\n `\\n⚠ Found ${orphanFiles.length} orphan prompt file${\n orphanFiles.length > 1 ? \"s\" : \"\"\n }:`\n )\n );\n\n for (const filePath of orphanFiles) {\n const promptName = FileManager.promptNameFromPath(filePath);\n const relativePath = path.relative(process.cwd(), filePath);\n\n console.log(chalk.yellow(` ${relativePath}`));\n console.log(\n chalk.gray(\n ` Add to prompts.json: \"${promptName}\": \"file:${relativePath}\"`\n )\n );\n }\n\n console.log(\n chalk.gray(\n `\\nTip: Add these to prompts.json to include them in sync operations.`\n )\n );\n }\n\n // Cleanup orphaned materialized files\n const currentDependencies = new Set(\n Object.keys(config.prompts).filter((name) => {\n const dependency = config.prompts[name];\n // Only include remote dependencies (not local file: dependencies)\n if (typeof dependency === \"object\" && dependency.file) {\n return false;\n }\n if (typeof dependency === \"string\" && dependency.startsWith(\"file:\")) {\n return false;\n }\n return true;\n })\n );\n\n const cleanedFiles =\n FileManager.cleanupOrphanedMaterializedFiles(currentDependencies);\n if (cleanedFiles.length > 0) {\n result.cleaned = cleanedFiles;\n FileManager.removeFromLock(lock, cleanedFiles);\n }\n\n // Save the updated lock file\n FileManager.savePromptsLock(lock);\n\n // Print individual results if there were actions\n if (result.fetched.length > 0) {\n for (const { name, version, versionSpec } of result.fetched) {\n // Get the actual saved path from lock file for display consistency\n const lockEntry = lock.prompts[name];\n const displayPath = lockEntry?.materialized\n ? `./${lockEntry.materialized}`\n : `./prompts/.materialized/${name}.prompt.yaml`;\n\n console.log(\n chalk.green(\n `✓ Pulled ${chalk.cyan(`${name}@${versionSpec}`)} ${chalk.gray(\n `(version ${version})`\n )} → ${chalk.gray(displayPath)}`\n )\n );\n }\n }\n\n if (result.pushed.length > 0) {\n for (const { name, version } of result.pushed) {\n const localPath = `./prompts/${name}.prompt.yaml`;\n console.log(\n chalk.green(\n `✓ Pushed ${chalk.cyan(name)} ${chalk.gray(\n `(version ${version})`\n )} from ${chalk.gray(localPath)}`\n )\n );\n }\n }\n\n // Print cleaned up files\n if (result.cleaned.length > 0) {\n for (const name of result.cleaned) {\n console.log(\n chalk.yellow(\n `✓ Cleaned ${chalk.cyan(name)} (no longer in dependencies)`\n )\n );\n }\n }\n\n // Print errors\n if (result.errors.length > 0) {\n for (const { name, error } of result.errors) {\n console.log(chalk.red(`✗ Failed ${chalk.cyan(name)}: ${error}`));\n }\n }\n\n // Print summary\n const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n const totalActions =\n result.fetched.length + result.pushed.length + result.cleaned.length;\n\n if (totalActions === 0 && result.errors.length === 0) {\n console.log(chalk.gray(`Synced in ${duration}s, no changes`));\n } else {\n const summary = [];\n if (result.fetched.length > 0)\n summary.push(`${result.fetched.length} fetched`);\n if (result.pushed.length > 0)\n summary.push(`${result.pushed.length} pushed`);\n if (result.cleaned.length > 0)\n summary.push(`${result.cleaned.length} cleaned`);\n if (result.errors.length > 0)\n summary.push(`${result.errors.length} errors`);\n\n console.log(chalk.gray(`Synced ${summary.join(\", \")} in ${duration}s`));\n }\n\n if (result.errors.length > 0) {\n process.exit(1);\n }\n } catch (error) {\n if (error instanceof PromptsError) {\n console.error(chalk.red(`Error: ${error.message}`));\n } else {\n console.error(\n chalk.red(\n `Unexpected error: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`\n )\n );\n }\n process.exit(1);\n }\n};\n"]}
@@ -4,11 +4,11 @@ import {
4
4
  import {
5
5
  PromptsApiService,
6
6
  PromptsError
7
- } from "./chunk-PLCZYSRL.mjs";
7
+ } from "./chunk-I3X7VMSP.mjs";
8
8
  import "./chunk-FEL5FLHA.mjs";
9
- import "./chunk-DQU2PZAL.mjs";
10
- import "./chunk-VJV532JA.mjs";
11
- import "./chunk-GNKQTK4I.mjs";
9
+ import "./chunk-VGVWXKVM.mjs";
10
+ import "./chunk-W6FD5ZO3.mjs";
11
+ import "./chunk-WHPBZSTS.mjs";
12
12
  import "./chunk-I2SOBPAF.mjs";
13
13
  import {
14
14
  ensureProjectInitialized
@@ -410,4 +410,4 @@ Tip: Add these to prompts.json to include them in sync operations.`
410
410
  export {
411
411
  syncCommand
412
412
  };
413
- //# sourceMappingURL=sync-QYFJZVU7.mjs.map
413
+ //# sourceMappingURL=sync-LL6TTFMS.mjs.map
@@ -2892,6 +2892,20 @@ type CreatePromptBody = NonNullable<paths["/api/prompts"]["post"]["requestBody"]
2892
2892
  type UpdatePromptBody = NonNullable<paths["/api/prompts/{id}"]["put"]["requestBody"]>["content"]["application/json"];
2893
2893
  type PromptResponse = NonNullable<paths["/api/prompts/{id}"]["get"]["responses"]["200"]["content"]["application/json"]>;
2894
2894
  type PromptScope = paths["/api/prompts"]["post"]["responses"]["200"]["content"]["application/json"]["scope"];
2895
+ /**
2896
+ * Fetch policy for prompt retrieval.
2897
+ * Controls how prompts are fetched and cached.
2898
+ */
2899
+ declare enum FetchPolicy {
2900
+ /** Use local file if available, otherwise fetch from API (default) */
2901
+ MATERIALIZED_FIRST = "MATERIALIZED_FIRST",
2902
+ /** Always try API first, fall back to materialized */
2903
+ ALWAYS_FETCH = "ALWAYS_FETCH",
2904
+ /** Fetch every X minutes, use materialized between fetches */
2905
+ CACHE_TTL = "CACHE_TTL",
2906
+ /** Never fetch, use materialized files only */
2907
+ MATERIALIZED_ONLY = "MATERIALIZED_ONLY"
2908
+ }
2895
2909
 
2896
2910
  /**
2897
2911
  * The Prompt class provides a standardized interface for working with prompt objects
@@ -3450,4 +3464,4 @@ interface LangWatchTracer extends Tracer {
3450
3464
  withActiveSpan<F extends (span: LangWatchSpan) => unknown>(name: string, options: LangWatchSpanOptions, context: Context, fn: F): ReturnType<F>;
3451
3465
  }
3452
3466
 
3453
- export { type ChatMessage as C, type InputOutputType as I, type JsonSerializable as J, type LangWatchSpan as L, type PromptResponse as P, type SpanType as S, type UpdatePromptBody as U, type LangWatchTracer as a, type LangWatchSpanMetrics as b, type LangWatchSpanRAGContext as c, type LangWatchSpanOptions as d, type SimpleChatMessage as e, INPUT_OUTPUT_TYPES as f, type CreatePromptBody as g, type PromptData as h, Prompt as i, type paths as p, spanTypes as s };
3467
+ export { type ChatMessage as C, FetchPolicy as F, type InputOutputType as I, type JsonSerializable as J, type LangWatchSpan as L, type PromptResponse as P, type SpanType as S, type UpdatePromptBody as U, type LangWatchTracer as a, type LangWatchSpanMetrics as b, type LangWatchSpanRAGContext as c, type LangWatchSpanOptions as d, type SimpleChatMessage as e, INPUT_OUTPUT_TYPES as f, type CreatePromptBody as g, type PromptData as h, Prompt as i, type paths as p, spanTypes as s };
@@ -2892,6 +2892,20 @@ type CreatePromptBody = NonNullable<paths["/api/prompts"]["post"]["requestBody"]
2892
2892
  type UpdatePromptBody = NonNullable<paths["/api/prompts/{id}"]["put"]["requestBody"]>["content"]["application/json"];
2893
2893
  type PromptResponse = NonNullable<paths["/api/prompts/{id}"]["get"]["responses"]["200"]["content"]["application/json"]>;
2894
2894
  type PromptScope = paths["/api/prompts"]["post"]["responses"]["200"]["content"]["application/json"]["scope"];
2895
+ /**
2896
+ * Fetch policy for prompt retrieval.
2897
+ * Controls how prompts are fetched and cached.
2898
+ */
2899
+ declare enum FetchPolicy {
2900
+ /** Use local file if available, otherwise fetch from API (default) */
2901
+ MATERIALIZED_FIRST = "MATERIALIZED_FIRST",
2902
+ /** Always try API first, fall back to materialized */
2903
+ ALWAYS_FETCH = "ALWAYS_FETCH",
2904
+ /** Fetch every X minutes, use materialized between fetches */
2905
+ CACHE_TTL = "CACHE_TTL",
2906
+ /** Never fetch, use materialized files only */
2907
+ MATERIALIZED_ONLY = "MATERIALIZED_ONLY"
2908
+ }
2895
2909
 
2896
2910
  /**
2897
2911
  * The Prompt class provides a standardized interface for working with prompt objects
@@ -3450,4 +3464,4 @@ interface LangWatchTracer extends Tracer {
3450
3464
  withActiveSpan<F extends (span: LangWatchSpan) => unknown>(name: string, options: LangWatchSpanOptions, context: Context, fn: F): ReturnType<F>;
3451
3465
  }
3452
3466
 
3453
- export { type ChatMessage as C, type InputOutputType as I, type JsonSerializable as J, type LangWatchSpan as L, type PromptResponse as P, type SpanType as S, type UpdatePromptBody as U, type LangWatchTracer as a, type LangWatchSpanMetrics as b, type LangWatchSpanRAGContext as c, type LangWatchSpanOptions as d, type SimpleChatMessage as e, INPUT_OUTPUT_TYPES as f, type CreatePromptBody as g, type PromptData as h, Prompt as i, type paths as p, spanTypes as s };
3467
+ export { type ChatMessage as C, FetchPolicy as F, type InputOutputType as I, type JsonSerializable as J, type LangWatchSpan as L, type PromptResponse as P, type SpanType as S, type UpdatePromptBody as U, type LangWatchTracer as a, type LangWatchSpanMetrics as b, type LangWatchSpanRAGContext as c, type LangWatchSpanOptions as d, type SimpleChatMessage as e, INPUT_OUTPUT_TYPES as f, type CreatePromptBody as g, type PromptData as h, Prompt as i, type paths as p, spanTypes as s };
package/package.json CHANGED
@@ -1,129 +1,147 @@
1
1
  {
2
- "name": "langwatch",
3
- "version": "0.8.2",
4
- "description": "LangWatch TypeScript/JavaScript SDK. Interact with the full LangWatch API and use the LangWatch OpenTelemetry SDK to instrument your application. For more information, see https://docs.langwatch.ai/integration/typescript/guide",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "author": "LangWatch",
9
- "license": "MIT",
10
- "engines": {
11
- "node": ">=20",
12
- "pnpm": ">=8"
13
- },
14
- "files": [
15
- "dist",
16
- "README.md",
17
- "LICENSE"
18
- ],
19
- "bin": {
20
- "langwatch": "./dist/cli/index.js"
21
- },
22
- "exports": {
23
- ".": {
24
- "types": "./dist/index.d.ts",
25
- "import": "./dist/index.mjs",
26
- "require": "./dist/index.js"
2
+ "name": "langwatch",
3
+ "version": "0.10.0",
4
+ "description": "LangWatch TypeScript/JavaScript SDK. Interact with the full LangWatch API and use the LangWatch OpenTelemetry SDK to instrument your application. For more information, see https://docs.langwatch.ai/integration/typescript/guide",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "author": "LangWatch",
9
+ "license": "MIT",
10
+ "engines": {
11
+ "node": ">=20",
12
+ "pnpm": ">=8"
27
13
  },
28
- "./observability": {
29
- "types": "./dist/observability-sdk/index.d.ts",
30
- "require": "./dist/observability-sdk/index.js",
31
- "import": "./dist/observability-sdk/index.mjs"
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "bin": {
20
+ "langwatch": "./dist/cli/index.js"
32
21
  },
33
- "./observability/node": {
34
- "types": "./dist/observability-sdk/setup/node/index.d.ts",
35
- "require": "./dist/observability-sdk/setup/node/index.js",
36
- "import": "./dist/observability-sdk/setup/node/index.mjs"
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.mjs",
26
+ "require": "./dist/index.js"
27
+ },
28
+ "./observability": {
29
+ "types": "./dist/observability-sdk/index.d.ts",
30
+ "require": "./dist/observability-sdk/index.js",
31
+ "import": "./dist/observability-sdk/index.mjs"
32
+ },
33
+ "./observability/node": {
34
+ "types": "./dist/observability-sdk/setup/node/index.d.ts",
35
+ "require": "./dist/observability-sdk/setup/node/index.js",
36
+ "import": "./dist/observability-sdk/setup/node/index.mjs"
37
+ },
38
+ "./observability/instrumentation/langchain": {
39
+ "types": "./dist/observability-sdk/instrumentation/langchain/index.d.ts",
40
+ "require": "./dist/observability-sdk/instrumentation/langchain/index.js",
41
+ "import": "./dist/observability-sdk/instrumentation/langchain/index.mjs"
42
+ }
37
43
  },
38
- "./observability/instrumentation/langchain": {
39
- "types": "./dist/observability-sdk/instrumentation/langchain/index.d.ts",
40
- "require": "./dist/observability-sdk/instrumentation/langchain/index.js",
41
- "import": "./dist/observability-sdk/instrumentation/langchain/index.mjs"
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/langwatch/langwatch.git",
47
+ "directory": "typescript-sdk"
48
+ },
49
+ "scripts": {
50
+ "prepare": "pnpm run generate:server-types && pnpm run generate:openapi-types",
51
+ "cli": "node dist/cli/index.js",
52
+ "lint": "eslint .",
53
+ "test": "vitest",
54
+ "test:unit": "vitest run --exclude '**/*.integration.test.ts'",
55
+ "test:e2e": "vitest run -c ./vitest.e2e.config.mts",
56
+ "test:seed": "dotenv -e .env.test -- bash -c 'cd ../langwatch && pnpm prisma:seed'",
57
+ "prebuild": "pnpm run prepare",
58
+ "build": "tsc --noEmit && tsup",
59
+ "tarball": "pnpm build && pnpm pack",
60
+ "typecheck": "tsc --noEmit",
61
+ "prepublish": "pnpm run build",
62
+ "generate:openapi-types": "pnpx openapi-typescript ../langwatch/src/app/api/openapiLangWatch.json -o ./src/internal/generated/openapi/api-client.ts",
63
+ "generate:server-types": "./copy-types.sh"
64
+ },
65
+ "devDependencies": {
66
+ "@eslint/js": "^9.32.0",
67
+ "@langchain/core": ">=0.3.68 <0.4.0",
68
+ "@langchain/langgraph": ">=0.4.0 <1.0.0",
69
+ "@langchain/openai": ">=0.6.0 <1.0.0",
70
+ "@opentelemetry/sdk-node": "0.205.0",
71
+ "@opentelemetry/sdk-trace-node": "^2.0.1",
72
+ "@opentelemetry/sdk-trace-web": ">=2.0.1",
73
+ "@types/debug": "^4.1.12",
74
+ "@types/js-yaml": "^4.0.9",
75
+ "@types/node": "^24.1.0",
76
+ "@typescript/native-preview": "7.0.0-dev.20250804.1",
77
+ "@vercel/otel": "^1.13.0",
78
+ "@vitest/coverage-v8": "3.2.4",
79
+ "esbuild": "^0.25.8",
80
+ "eslint": "^9.32.0",
81
+ "fets": "^0.8.5",
82
+ "fishery": "^2.3.1",
83
+ "langchain": ">=0.3.0 <1.0.0",
84
+ "msw": "^2.10.4",
85
+ "nock": "^14.0.8",
86
+ "openapi-msw": "^1.2.0",
87
+ "ts-to-zod": "4.0.1",
88
+ "tsup": "^8.5.0",
89
+ "typescript": "^5.9.2",
90
+ "typescript-eslint": "^8.38.0",
91
+ "vitest": "^3.2.4",
92
+ "vitest-mock-extended": "^3.1.0",
93
+ "yaml": "^2.8.1"
94
+ },
95
+ "dependencies": {
96
+ "@opentelemetry/api": "^1.9.0",
97
+ "@opentelemetry/api-logs": "0.205.0",
98
+ "@opentelemetry/core": "^2.0.1",
99
+ "@opentelemetry/exporter-logs-otlp-http": "0.205.0",
100
+ "@opentelemetry/exporter-trace-otlp-http": "0.205.0",
101
+ "@opentelemetry/instrumentation": "0.205.0",
102
+ "@opentelemetry/resources": "^2.0.1",
103
+ "@opentelemetry/sdk-logs": "0.205.0",
104
+ "@opentelemetry/sdk-metrics": "^2.0.1",
105
+ "@opentelemetry/sdk-trace-base": "^2.0.1",
106
+ "@opentelemetry/semantic-conventions": "^1.36.0",
107
+ "@types/prompts": "^2.4.9",
108
+ "chalk": "^4.1.2",
109
+ "commander": "^12.0.0",
110
+ "dotenv": "^16.6.1",
111
+ "js-yaml": "^4.1.0",
112
+ "liquidjs": "^10.21.1",
113
+ "open": "^10.2.0",
114
+ "openapi-fetch": "^0.14.0",
115
+ "ora": "^5.4.1",
116
+ "prompts": "^2.4.2",
117
+ "xksuid": "^0.0.4",
118
+ "zod": "^4.0.14"
119
+ },
120
+ "peerDependencies": {
121
+ "@ai-sdk/openai": ">=2.0.0 <3.0.0",
122
+ "@langchain/core": ">=0.3.0 <1.0.0",
123
+ "@langchain/langgraph": ">=0.4.0 <1.0.0",
124
+ "@langchain/openai": ">=0.6.0 <1.0.0",
125
+ "@opentelemetry/context-async-hooks": "^2.1.0",
126
+ "@opentelemetry/context-zone": ">=1.19.0 <3.0.0",
127
+ "@opentelemetry/sdk-node": ">=0.200.0 <1.0.0",
128
+ "@opentelemetry/sdk-trace-web": ">=1.19.0 <3.0.0",
129
+ "langchain": ">=0.3.0 <1.0.0"
130
+ },
131
+ "pnpm": {
132
+ "overrides": {
133
+ "@opentelemetry/api": "^1.9.0",
134
+ "@opentelemetry/core": "^2.0.1",
135
+ "@opentelemetry/resources": "^2.0.1",
136
+ "@opentelemetry/sdk-trace-base": "^2.0.1",
137
+ "@opentelemetry/instrumentation": "0.205.0",
138
+ "@opentelemetry/sdk-node": "0.205.0",
139
+ "@opentelemetry/context-async-hooks": "^2.1.0",
140
+ "@opentelemetry/api-logs": "0.205.0",
141
+ "@opentelemetry/sdk-logs": "0.205.0",
142
+ "@opentelemetry/exporter-logs-otlp-http": "0.205.0",
143
+ "@opentelemetry/exporter-trace-otlp-http": "0.205.0",
144
+ "zod": "^4.0.14"
145
+ }
42
146
  }
43
- },
44
- "repository": {
45
- "type": "git",
46
- "url": "https://github.com/langwatch/langwatch.git",
47
- "directory": "typescript-sdk"
48
- },
49
- "devDependencies": {
50
- "@eslint/js": "^9.32.0",
51
- "@langchain/core": ">=0.3.68 <0.4.0",
52
- "@langchain/langgraph": ">=0.4.0 <1.0.0",
53
- "@langchain/openai": ">=0.6.0 <1.0.0",
54
- "@opentelemetry/sdk-node": "0.205.0",
55
- "@opentelemetry/sdk-trace-node": "^2.0.1",
56
- "@opentelemetry/sdk-trace-web": ">=2.0.1",
57
- "@types/debug": "^4.1.12",
58
- "@types/js-yaml": "^4.0.9",
59
- "@types/node": "^24.1.0",
60
- "@typescript/native-preview": "7.0.0-dev.20250804.1",
61
- "@vercel/otel": "^1.13.0",
62
- "@vitest/coverage-v8": "3.2.4",
63
- "esbuild": "^0.25.8",
64
- "eslint": "^9.32.0",
65
- "fets": "^0.8.5",
66
- "fishery": "^2.3.1",
67
- "langchain": ">=0.3.0 <1.0.0",
68
- "msw": "^2.10.4",
69
- "nock": "^14.0.8",
70
- "openapi-msw": "^1.2.0",
71
- "ts-to-zod": "4.0.1",
72
- "tsup": "^8.5.0",
73
- "typescript": "^5.9.2",
74
- "typescript-eslint": "^8.38.0",
75
- "vitest": "^3.2.4",
76
- "vitest-mock-extended": "^3.1.0",
77
- "yaml": "^2.8.1"
78
- },
79
- "dependencies": {
80
- "@opentelemetry/api": "^1.9.0",
81
- "@opentelemetry/api-logs": "0.205.0",
82
- "@opentelemetry/core": "^2.0.1",
83
- "@opentelemetry/exporter-logs-otlp-http": "0.205.0",
84
- "@opentelemetry/exporter-trace-otlp-http": "0.205.0",
85
- "@opentelemetry/instrumentation": "0.205.0",
86
- "@opentelemetry/resources": "^2.0.1",
87
- "@opentelemetry/sdk-logs": "0.205.0",
88
- "@opentelemetry/sdk-metrics": "^2.0.1",
89
- "@opentelemetry/sdk-trace-base": "^2.0.1",
90
- "@opentelemetry/semantic-conventions": "^1.36.0",
91
- "@types/prompts": "^2.4.9",
92
- "chalk": "^4.1.2",
93
- "commander": "^12.0.0",
94
- "dotenv": "^16.6.1",
95
- "js-yaml": "^4.1.0",
96
- "liquidjs": "^10.21.1",
97
- "open": "^10.2.0",
98
- "openapi-fetch": "^0.14.0",
99
- "ora": "^5.4.1",
100
- "prompts": "^2.4.2",
101
- "xksuid": "^0.0.4",
102
- "zod": "^4.0.14"
103
- },
104
- "peerDependencies": {
105
- "@ai-sdk/openai": ">=2.0.0 <3.0.0",
106
- "@langchain/core": ">=0.3.0 <1.0.0",
107
- "@langchain/langgraph": ">=0.4.0 <1.0.0",
108
- "@langchain/openai": ">=0.6.0 <1.0.0",
109
- "@opentelemetry/context-async-hooks": "^2.1.0",
110
- "@opentelemetry/context-zone": ">=1.19.0 <3.0.0",
111
- "@opentelemetry/sdk-node": ">=0.200.0 <1.0.0",
112
- "@opentelemetry/sdk-trace-web": ">=1.19.0 <3.0.0",
113
- "langchain": ">=0.3.0 <1.0.0"
114
- },
115
- "scripts": {
116
- "cli": "node dist/cli/index.js",
117
- "lint": "eslint .",
118
- "test": "vitest",
119
- "test:unit": "vitest run --exclude '**/*.integration.test.ts'",
120
- "test:e2e": "vitest run -c ./vitest.e2e.config.mts",
121
- "prebuild": "pnpm run prepare",
122
- "build": "tsc --noEmit && tsup",
123
- "tarball": "pnpm build && pnpm pack",
124
- "typecheck": "tsc --noEmit",
125
- "prepublish": "pnpm run build",
126
- "generate:openapi-types": "npx openapi-typescript ../langwatch/src/app/api/openapiLangWatch.json -o ./src/internal/generated/openapi/api-client.ts",
127
- "generate:server-types": "./copy-types.sh"
128
- }
129
- }
147
+ }