langwatch 0.3.1 → 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 (203) hide show
  1. package/README.md +5 -2
  2. package/dist/{add-LBBS4I3H.js → add-35QACTIV.js} +34 -28
  3. package/dist/add-35QACTIV.js.map +1 -0
  4. package/dist/{add-RD3ZKFAT.mjs → add-TRJAXM4D.mjs} +22 -16
  5. package/dist/add-TRJAXM4D.mjs.map +1 -0
  6. package/dist/chunk-4ZSSHX6F.js +636 -0
  7. package/dist/chunk-4ZSSHX6F.js.map +1 -0
  8. package/dist/chunk-5EVBOHJY.js +155 -0
  9. package/dist/chunk-5EVBOHJY.js.map +1 -0
  10. package/dist/{chunk-YN4436PK.mjs → chunk-CU3443HD.mjs} +14 -9
  11. package/dist/{chunk-2JU376G7.js → chunk-D2CSG4SJ.js} +4 -4
  12. package/dist/chunk-D2CSG4SJ.js.map +1 -0
  13. package/dist/chunk-DISMHYXC.js +184 -0
  14. package/dist/chunk-DISMHYXC.js.map +1 -0
  15. package/dist/{chunk-E7UE2MPD.mjs → chunk-ECUXLXFT.mjs} +2 -2
  16. package/dist/chunk-EJWJXTPU.mjs +626 -0
  17. package/dist/chunk-EJWJXTPU.mjs.map +1 -0
  18. package/dist/chunk-GQMDZ4GY.mjs +155 -0
  19. package/dist/chunk-GQMDZ4GY.mjs.map +1 -0
  20. package/dist/{chunk-3GKPQB4R.mjs → chunk-HUI45ULC.mjs} +4 -4
  21. package/dist/chunk-HUI45ULC.mjs.map +1 -0
  22. package/dist/{chunk-HJU67C7H.js → chunk-K64Y6YUG.js} +10 -10
  23. package/dist/{chunk-HJU67C7H.js.map → chunk-K64Y6YUG.js.map} +1 -1
  24. package/dist/chunk-LP76VXI3.mjs +636 -0
  25. package/dist/chunk-LP76VXI3.mjs.map +1 -0
  26. package/dist/chunk-M4VUHTT2.js +626 -0
  27. package/dist/chunk-M4VUHTT2.js.map +1 -0
  28. package/dist/{chunk-PR3JDWC3.mjs → chunk-N2V6J3U2.mjs} +28 -3
  29. package/dist/chunk-N2V6J3U2.mjs.map +1 -0
  30. package/dist/chunk-OUCVXP4G.js +258 -0
  31. package/dist/chunk-OUCVXP4G.js.map +1 -0
  32. package/dist/{chunk-FJLK5CFL.js → chunk-OXBO24RB.js} +13 -8
  33. package/dist/chunk-OXBO24RB.js.map +1 -0
  34. package/dist/chunk-PGWR3OQY.mjs +258 -0
  35. package/dist/chunk-PGWR3OQY.mjs.map +1 -0
  36. package/dist/{chunk-SMXXAVMB.js → chunk-SGNJDRCT.js} +2 -2
  37. package/dist/chunk-SGNJDRCT.js.map +1 -0
  38. package/dist/{chunk-W5ZEP3CI.mjs → chunk-SYMZPWZE.mjs} +2 -2
  39. package/dist/chunk-SYMZPWZE.mjs.map +1 -0
  40. package/dist/{chunk-KGDAENGD.js → chunk-YH5TIVK2.js} +28 -3
  41. package/dist/chunk-YH5TIVK2.js.map +1 -0
  42. package/dist/chunk-YNQ44U6D.mjs +184 -0
  43. package/dist/chunk-YNQ44U6D.mjs.map +1 -0
  44. package/dist/cli/index.js +8 -8
  45. package/dist/cli/index.mjs +8 -8
  46. package/dist/{create-G5MTGOOH.js → create-7K2CC4KQ.js} +11 -11
  47. package/dist/{create-G5MTGOOH.js.map → create-7K2CC4KQ.js.map} +1 -1
  48. package/dist/{create-QUZYBMQB.mjs → create-MK7NEGCM.mjs} +8 -8
  49. package/dist/implementation-C4lvooSg.d.mts +576 -0
  50. package/dist/implementation-CzemP9jY.d.ts +576 -0
  51. package/dist/index-DTEZr0Jn.d.mts +34 -0
  52. package/dist/index-DTEZr0Jn.d.ts +34 -0
  53. package/dist/index.d.mts +122 -41
  54. package/dist/index.d.ts +122 -41
  55. package/dist/index.js +16 -12
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.mjs +27 -23
  58. package/dist/index.mjs.map +1 -1
  59. package/dist/init-GDKJICSS.js +16 -0
  60. package/dist/{init-XU2JFY6N.js.map → init-GDKJICSS.js.map} +1 -1
  61. package/dist/{init-H67RW22E.mjs → init-RINSTP4L.mjs} +5 -5
  62. package/dist/{list-7NPSX2E4.mjs → list-7L23G5DY.mjs} +28 -16
  63. package/dist/list-7L23G5DY.mjs.map +1 -0
  64. package/dist/{list-ZXFLAF52.js → list-OLLQ7XKZ.js} +29 -17
  65. package/dist/list-OLLQ7XKZ.js.map +1 -0
  66. package/dist/{login-EK4WVOI2.mjs → login-RCNKL5AM.mjs} +6 -5
  67. package/dist/login-RCNKL5AM.mjs.map +1 -0
  68. package/dist/{login-76NQIHKR.js → login-XF3BQQPV.js} +7 -6
  69. package/dist/login-XF3BQQPV.js.map +1 -0
  70. package/dist/observability-sdk/index.d.mts +134 -0
  71. package/dist/observability-sdk/index.d.ts +134 -0
  72. package/dist/observability-sdk/index.js +41 -0
  73. package/dist/observability-sdk/index.js.map +1 -0
  74. package/dist/observability-sdk/index.mjs +41 -0
  75. package/dist/observability-sdk/instrumentation/langchain/index.d.mts +69 -0
  76. package/dist/observability-sdk/instrumentation/langchain/index.d.ts +69 -0
  77. package/dist/observability-sdk/instrumentation/langchain/index.js +518 -0
  78. package/dist/observability-sdk/instrumentation/langchain/index.js.map +1 -0
  79. package/dist/observability-sdk/instrumentation/langchain/index.mjs +518 -0
  80. package/dist/observability-sdk/instrumentation/langchain/index.mjs.map +1 -0
  81. package/dist/observability-sdk/setup/node/index.d.mts +368 -0
  82. package/dist/observability-sdk/setup/node/index.d.ts +368 -0
  83. package/dist/observability-sdk/setup/node/index.js +276 -0
  84. package/dist/observability-sdk/setup/node/index.js.map +1 -0
  85. package/dist/observability-sdk/setup/node/index.mjs +276 -0
  86. package/dist/observability-sdk/setup/node/index.mjs.map +1 -0
  87. package/dist/{remove-SDJYEPAY.mjs → remove-3VLQNVHN.mjs} +11 -8
  88. package/dist/remove-3VLQNVHN.mjs.map +1 -0
  89. package/dist/{remove-XBNGIVMR.js → remove-L6JVJBWY.js} +18 -15
  90. package/dist/remove-L6JVJBWY.js.map +1 -0
  91. package/dist/{sync-ST2IWXSB.mjs → sync-DPMTUTVL.mjs} +39 -33
  92. package/dist/sync-DPMTUTVL.mjs.map +1 -0
  93. package/dist/{sync-EISKGPTL.js → sync-PSU3F5Z4.js} +52 -46
  94. package/dist/sync-PSU3F5Z4.js.map +1 -0
  95. package/dist/{prompt-D-jpMrLS.d.mts → types-1q5wIYP5.d.mts} +628 -14
  96. package/dist/{prompt-D-jpMrLS.d.ts → types-C9k5gGhU.d.ts} +628 -14
  97. package/dist/types-DRiQaKFG.d.mts +254 -0
  98. package/dist/types-DRiQaKFG.d.ts +254 -0
  99. package/dist/types-Dmazk5Bk.d.mts +44 -0
  100. package/dist/types-Dmazk5Bk.d.ts +44 -0
  101. package/package.json +40 -40
  102. package/dist/add-LBBS4I3H.js.map +0 -1
  103. package/dist/add-RD3ZKFAT.mjs.map +0 -1
  104. package/dist/chunk-2JU376G7.js.map +0 -1
  105. package/dist/chunk-2ODBGSBI.js +0 -4
  106. package/dist/chunk-2ODBGSBI.js.map +0 -1
  107. package/dist/chunk-3GKPQB4R.mjs.map +0 -1
  108. package/dist/chunk-52GXX3MA.js +0 -426
  109. package/dist/chunk-52GXX3MA.js.map +0 -1
  110. package/dist/chunk-5NC5ILKA.js +0 -94
  111. package/dist/chunk-5NC5ILKA.js.map +0 -1
  112. package/dist/chunk-6I4EA43Y.js +0 -39
  113. package/dist/chunk-6I4EA43Y.js.map +0 -1
  114. package/dist/chunk-DTEKFQ4U.js +0 -159
  115. package/dist/chunk-DTEKFQ4U.js.map +0 -1
  116. package/dist/chunk-F63YKTXA.mjs +0 -47
  117. package/dist/chunk-F63YKTXA.mjs.map +0 -1
  118. package/dist/chunk-FJLK5CFL.js.map +0 -1
  119. package/dist/chunk-GJSEBQXF.mjs +0 -392
  120. package/dist/chunk-GJSEBQXF.mjs.map +0 -1
  121. package/dist/chunk-J7ICRUU4.mjs +0 -426
  122. package/dist/chunk-J7ICRUU4.mjs.map +0 -1
  123. package/dist/chunk-KGDAENGD.js.map +0 -1
  124. package/dist/chunk-LD74LVRU.js +0 -47
  125. package/dist/chunk-LD74LVRU.js.map +0 -1
  126. package/dist/chunk-PCQVQ7SB.js +0 -45
  127. package/dist/chunk-PCQVQ7SB.js.map +0 -1
  128. package/dist/chunk-PR3JDWC3.mjs.map +0 -1
  129. package/dist/chunk-PWZBLTHR.js +0 -118
  130. package/dist/chunk-PWZBLTHR.js.map +0 -1
  131. package/dist/chunk-QEWDG5QE.mjs +0 -45
  132. package/dist/chunk-QEWDG5QE.mjs.map +0 -1
  133. package/dist/chunk-SMXXAVMB.js.map +0 -1
  134. package/dist/chunk-STV4ZVNA.mjs +0 -118
  135. package/dist/chunk-STV4ZVNA.mjs.map +0 -1
  136. package/dist/chunk-T5AZMMVS.mjs +0 -94
  137. package/dist/chunk-T5AZMMVS.mjs.map +0 -1
  138. package/dist/chunk-UU33HCCZ.mjs +0 -159
  139. package/dist/chunk-UU33HCCZ.mjs.map +0 -1
  140. package/dist/chunk-VGHLQXKB.js +0 -392
  141. package/dist/chunk-VGHLQXKB.js.map +0 -1
  142. package/dist/chunk-W5ZEP3CI.mjs.map +0 -1
  143. package/dist/chunk-Y666BJA5.mjs +0 -4
  144. package/dist/chunk-YFUZF7JM.mjs +0 -39
  145. package/dist/chunk-YFUZF7JM.mjs.map +0 -1
  146. package/dist/chunk-YN4436PK.mjs.map +0 -1
  147. package/dist/client-B2HqIKg6.d.ts +0 -51
  148. package/dist/client-XyCqclCi.d.mts +0 -51
  149. package/dist/client-browser.d.mts +0 -8
  150. package/dist/client-browser.d.ts +0 -8
  151. package/dist/client-browser.js +0 -85
  152. package/dist/client-browser.js.map +0 -1
  153. package/dist/client-browser.mjs +0 -85
  154. package/dist/client-browser.mjs.map +0 -1
  155. package/dist/client-node.d.mts +0 -8
  156. package/dist/client-node.d.ts +0 -8
  157. package/dist/client-node.js +0 -92
  158. package/dist/client-node.js.map +0 -1
  159. package/dist/client-node.mjs +0 -92
  160. package/dist/client-node.mjs.map +0 -1
  161. package/dist/evaluation/index.d.mts +0 -897
  162. package/dist/evaluation/index.d.ts +0 -897
  163. package/dist/evaluation/index.js +0 -14
  164. package/dist/evaluation/index.js.map +0 -1
  165. package/dist/evaluation/index.mjs +0 -14
  166. package/dist/filterable-batch-span-processor-zO5kcjBY.d.mts +0 -64
  167. package/dist/filterable-batch-span-processor-zO5kcjBY.d.ts +0 -64
  168. package/dist/init-XU2JFY6N.js +0 -16
  169. package/dist/list-7NPSX2E4.mjs.map +0 -1
  170. package/dist/list-ZXFLAF52.js.map +0 -1
  171. package/dist/login-76NQIHKR.js.map +0 -1
  172. package/dist/login-EK4WVOI2.mjs.map +0 -1
  173. package/dist/observability/index.d.mts +0 -260
  174. package/dist/observability/index.d.ts +0 -260
  175. package/dist/observability/index.js +0 -21
  176. package/dist/observability/index.js.map +0 -1
  177. package/dist/observability/index.mjs +0 -21
  178. package/dist/observability/index.mjs.map +0 -1
  179. package/dist/observability/instrumentation/langchain/index.d.mts +0 -40
  180. package/dist/observability/instrumentation/langchain/index.d.ts +0 -40
  181. package/dist/observability/instrumentation/langchain/index.js +0 -668
  182. package/dist/observability/instrumentation/langchain/index.js.map +0 -1
  183. package/dist/observability/instrumentation/langchain/index.mjs +0 -668
  184. package/dist/observability/instrumentation/langchain/index.mjs.map +0 -1
  185. package/dist/prompt/index.d.mts +0 -10
  186. package/dist/prompt/index.d.ts +0 -10
  187. package/dist/prompt/index.js +0 -22
  188. package/dist/prompt/index.js.map +0 -1
  189. package/dist/prompt/index.mjs +0 -22
  190. package/dist/prompt/index.mjs.map +0 -1
  191. package/dist/record-evaluation-CmxMXa-3.d.mts +0 -25
  192. package/dist/record-evaluation-CmxMXa-3.d.ts +0 -25
  193. package/dist/remove-SDJYEPAY.mjs.map +0 -1
  194. package/dist/remove-XBNGIVMR.js.map +0 -1
  195. package/dist/sync-EISKGPTL.js.map +0 -1
  196. package/dist/sync-ST2IWXSB.mjs.map +0 -1
  197. package/dist/trace-CqaKo0kZ.d.ts +0 -622
  198. package/dist/trace-DtVc5GhF.d.mts +0 -622
  199. /package/dist/{chunk-Y666BJA5.mjs.map → chunk-CU3443HD.mjs.map} +0 -0
  200. /package/dist/{chunk-E7UE2MPD.mjs.map → chunk-ECUXLXFT.mjs.map} +0 -0
  201. /package/dist/{create-QUZYBMQB.mjs.map → create-MK7NEGCM.mjs.map} +0 -0
  202. /package/dist/{init-H67RW22E.mjs.map → init-RINSTP4L.mjs.map} +0 -0
  203. /package/dist/{evaluation → observability-sdk}/index.mjs.map +0 -0
@@ -1,24 +1,27 @@
1
- import {
2
- ensureProjectInitialized
3
- } from "./chunk-E7UE2MPD.mjs";
4
- import {
5
- FileManager
6
- } from "./chunk-3GKPQB4R.mjs";
7
1
  import {
8
2
  checkApiKey
9
3
  } from "./chunk-DHJKJVY7.mjs";
10
- import "./chunk-4NRLVT2U.mjs";
11
4
  import {
12
- PromptService,
5
+ LangWatch
6
+ } from "./chunk-GQMDZ4GY.mjs";
7
+ import {
13
8
  PromptsError
14
- } from "./chunk-GJSEBQXF.mjs";
9
+ } from "./chunk-LP76VXI3.mjs";
10
+ import "./chunk-N2V6J3U2.mjs";
11
+ import "./chunk-EJWJXTPU.mjs";
12
+ import "./chunk-PGWR3OQY.mjs";
13
+ import "./chunk-YNQ44U6D.mjs";
15
14
  import {
16
- PromptConverter
17
- } from "./chunk-W5ZEP3CI.mjs";
18
- import "./chunk-QEWDG5QE.mjs";
15
+ ensureProjectInitialized
16
+ } from "./chunk-ECUXLXFT.mjs";
17
+ import {
18
+ FileManager
19
+ } from "./chunk-HUI45ULC.mjs";
19
20
  import {
20
- __require
21
- } from "./chunk-YN4436PK.mjs";
21
+ PromptConverter
22
+ } from "./chunk-SYMZPWZE.mjs";
23
+ import "./chunk-4NRLVT2U.mjs";
24
+ import "./chunk-CU3443HD.mjs";
22
25
 
23
26
  // src/cli/commands/sync.ts
24
27
  import * as fs from "fs";
@@ -26,6 +29,7 @@ import * as path from "path";
26
29
  import chalk from "chalk";
27
30
  import ora from "ora";
28
31
  import * as yaml from "js-yaml";
32
+ import readline from "readline";
29
33
  var handleConflict = async (promptName, conflictInfo) => {
30
34
  console.log(
31
35
  chalk.yellow(
@@ -48,7 +52,6 @@ var handleConflict = async (promptName, conflictInfo) => {
48
52
  console.log(" [l] Use local version (overwrite remote)");
49
53
  console.log(" [r] Use remote version (overwrite local)");
50
54
  console.log(" [a] Abort sync for this prompt");
51
- const readline = __require("readline");
52
55
  const rl = readline.createInterface({
53
56
  input: process.stdin,
54
57
  output: process.stdout
@@ -68,11 +71,11 @@ var handleConflict = async (promptName, conflictInfo) => {
68
71
  });
69
72
  };
70
73
  var syncCommand = async () => {
71
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
74
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
72
75
  const startTime = Date.now();
73
76
  try {
74
77
  checkApiKey();
75
- const promptService = PromptService.getInstance();
78
+ const langwatch = new LangWatch();
76
79
  await ensureProjectInitialized(false);
77
80
  const config = FileManager.loadPromptsConfig();
78
81
  const lock = FileManager.loadPromptsLock();
@@ -100,9 +103,9 @@ var syncCommand = async () => {
100
103
  ).start();
101
104
  for (const [name, dependency] of remoteDeps) {
102
105
  try {
103
- const versionSpec = typeof dependency === "string" ? dependency : dependency.version || "latest";
106
+ const versionSpec = typeof dependency === "string" ? dependency : (_a = dependency.version) != null ? _a : "latest";
104
107
  const lockEntry = lock.prompts[name];
105
- const prompt = await promptService.get(name);
108
+ const prompt = await langwatch.prompts.get(name);
106
109
  if (prompt) {
107
110
  const needsUpdate = !lockEntry || lockEntry.version !== prompt.version || !lockEntry.materialized || !fs.existsSync(path.resolve(lockEntry.materialized));
108
111
  if (needsUpdate) {
@@ -154,19 +157,19 @@ var syncCommand = async () => {
154
157
  try {
155
158
  const filePath = dependency.slice(5);
156
159
  const localConfig = FileManager.loadLocalPrompt(filePath);
157
- const currentVersion = (_a = lock.prompts[promptName]) == null ? void 0 : _a.version;
160
+ const currentVersion = (_b = lock.prompts[promptName]) == null ? void 0 : _b.version;
158
161
  const configData = {
159
162
  model: localConfig.model,
160
163
  prompt: PromptConverter.extractSystemPrompt(localConfig.messages),
161
164
  messages: PromptConverter.filterNonSystemMessages(
162
165
  localConfig.messages
163
166
  ),
164
- temperature: (_b = localConfig.modelParameters) == null ? void 0 : _b.temperature,
165
- max_tokens: (_c = localConfig.modelParameters) == null ? void 0 : _c.max_tokens,
167
+ temperature: (_c = localConfig.modelParameters) == null ? void 0 : _c.temperature,
168
+ max_tokens: (_d = localConfig.modelParameters) == null ? void 0 : _d.max_tokens,
166
169
  inputs: [{ identifier: "input", type: "str" }],
167
170
  outputs: [{ identifier: "output", type: "str" }]
168
171
  };
169
- const syncResult = await promptService.sync({
172
+ const syncResult = await langwatch.prompts.sync({
170
173
  name: promptName,
171
174
  configData,
172
175
  localVersion: currentVersion,
@@ -199,7 +202,7 @@ var syncCommand = async () => {
199
202
  role: "system",
200
203
  content: syncResult.conflictInfo.remoteConfigData.prompt
201
204
  },
202
- ...(_d = syncResult.conflictInfo.remoteConfigData.messages) != null ? _d : []
205
+ ...(_e = syncResult.conflictInfo.remoteConfigData.messages) != null ? _e : []
203
206
  ]
204
207
  };
205
208
  const yamlContent = yaml.dump(remoteConfig, {
@@ -218,7 +221,7 @@ var syncCommand = async () => {
218
221
  materialized: filePath
219
222
  };
220
223
  } else if (syncResult.action === "conflict") {
221
- const remoteVersion = (_f = (_e = syncResult.conflictInfo) == null ? void 0 : _e.remoteVersion) != null ? _f : 0;
224
+ const remoteVersion = (_g = (_f = syncResult.conflictInfo) == null ? void 0 : _f.remoteVersion) != null ? _g : 0;
222
225
  if (conflictResolution === "remote") {
223
226
  lock.prompts[promptName] = {
224
227
  version: remoteVersion,
@@ -241,7 +244,7 @@ var syncCommand = async () => {
241
244
  actionText = "Pulled";
242
245
  result.fetched.push({
243
246
  name: promptName,
244
- version: ((_g = syncResult.conflictInfo) == null ? void 0 : _g.remoteVersion) || 0,
247
+ version: (_i = (_h = syncResult.conflictInfo) == null ? void 0 : _h.remoteVersion) != null ? _i : 0,
245
248
  versionSpec: "latest"
246
249
  // Default for conflict resolution
247
250
  });
@@ -249,7 +252,7 @@ var syncCommand = async () => {
249
252
  actionText = "Pushed";
250
253
  result.pushed.push({
251
254
  name: promptName,
252
- version: (((_h = syncResult.conflictInfo) == null ? void 0 : _h.remoteVersion) || 0) + 1
255
+ version: ((_k = (_j = syncResult.conflictInfo) == null ? void 0 : _j.remoteVersion) != null ? _k : 0) + 1
253
256
  // New version after push
254
257
  });
255
258
  }
@@ -257,19 +260,22 @@ var syncCommand = async () => {
257
260
  actionText = "Up-to-date";
258
261
  result.unchanged.push(promptName);
259
262
  } else {
260
- actionText = {
263
+ const actionMap = {
261
264
  created: "Created",
262
- updated: "Updated"
263
- }[syncResult.action] || "Pushed";
265
+ updated: "Updated",
266
+ conflict: "Conflict resolved",
267
+ up_to_date: "Up to date"
268
+ };
269
+ actionText = actionMap[syncResult.action] || "Pushed";
264
270
  result.pushed.push({
265
271
  name: promptName,
266
- version: ((_i = syncResult.prompt) == null ? void 0 : _i.version) || 0
272
+ version: (_m = (_l = syncResult.prompt) == null ? void 0 : _l.version) != null ? _m : 0
267
273
  });
268
274
  }
269
275
  pushSpinner.text = `${actionText} ${chalk.cyan(
270
276
  promptName
271
277
  )} ${chalk.gray(
272
- `(version ${((_j = syncResult.prompt) == null ? void 0 : _j.version) || ((_k = syncResult.conflictInfo) == null ? void 0 : _k.remoteVersion) || "unknown"})`
278
+ `(version ${(_q = (_p = (_n = syncResult.prompt) == null ? void 0 : _n.version) != null ? _p : (_o = syncResult.conflictInfo) == null ? void 0 : _o.remoteVersion) != null ? _q : "unknown"})`
273
279
  )} ${conflictResolution === "remote" ? "to" : "from"} ${chalk.gray(
274
280
  relativePath
275
281
  )}`;
@@ -400,4 +406,4 @@ Tip: Add these to prompts.json to include them in sync operations.`
400
406
  export {
401
407
  syncCommand
402
408
  };
403
- //# sourceMappingURL=sync-ST2IWXSB.mjs.map
409
+ //# sourceMappingURL=sync-DPMTUTVL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/sync.ts"],"sourcesContent":["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 { type ConfigData, PromptsError, type SyncAction } from \"@/client-sdk/services/prompts\";\nimport { LangWatch } from \"@/client-sdk\";\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 `\\n⚠ Conflict detected for prompt: ${chalk.cyan(promptName)}`,\n ),\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 const startTime = Date.now();\n\n try {\n // Check API key before doing anything else\n checkApiKey();\n\n // Get LangWatch client\n const langwatch = new LangWatch();\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 langwatch.prompts.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 langwatch.prompts.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 - create new version (remote + 1)\n lock.prompts[promptName] = {\n version: remoteVersion + 1,\n versionId: \"conflict_resolved\", // Temporary until we get actual 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(`(version ${version})`)} 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"],"mappings":"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","names":["resolve"]}
@@ -1,24 +1,27 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2
2
 
3
- var _chunkHJU67C7Hjs = require('./chunk-HJU67C7H.js');
4
-
3
+ var _chunkF6E4XQQUjs = require('./chunk-F6E4XQQU.js');
5
4
 
6
- var _chunk2JU376G7js = require('./chunk-2JU376G7.js');
7
5
 
6
+ var _chunk5EVBOHJYjs = require('./chunk-5EVBOHJY.js');
8
7
 
9
- var _chunkF6E4XQQUjs = require('./chunk-F6E4XQQU.js');
10
- require('./chunk-HA3LI5IK.js');
11
8
 
9
+ var _chunk4ZSSHX6Fjs = require('./chunk-4ZSSHX6F.js');
10
+ require('./chunk-YH5TIVK2.js');
11
+ require('./chunk-M4VUHTT2.js');
12
+ require('./chunk-OUCVXP4G.js');
13
+ require('./chunk-DISMHYXC.js');
12
14
 
13
15
 
14
- var _chunkVGHLQXKBjs = require('./chunk-VGHLQXKB.js');
16
+ var _chunkK64Y6YUGjs = require('./chunk-K64Y6YUG.js');
15
17
 
16
18
 
17
- var _chunkSMXXAVMBjs = require('./chunk-SMXXAVMB.js');
18
- require('./chunk-PCQVQ7SB.js');
19
+ var _chunkD2CSG4SJjs = require('./chunk-D2CSG4SJ.js');
19
20
 
20
21
 
21
- var _chunkFJLK5CFLjs = require('./chunk-FJLK5CFL.js');
22
+ var _chunkSGNJDRCTjs = require('./chunk-SGNJDRCT.js');
23
+ require('./chunk-HA3LI5IK.js');
24
+ require('./chunk-OXBO24RB.js');
22
25
 
23
26
  // src/cli/commands/sync.ts
24
27
  var _fs = require('fs'); var fs = _interopRequireWildcard(_fs);
@@ -26,6 +29,7 @@ var _path = require('path'); var path = _interopRequireWildcard(_path);
26
29
  var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
27
30
  var _ora = require('ora'); var _ora2 = _interopRequireDefault(_ora);
28
31
  var _jsyaml = require('js-yaml'); var yaml = _interopRequireWildcard(_jsyaml);
32
+ var _readline = require('readline'); var _readline2 = _interopRequireDefault(_readline);
29
33
  var handleConflict = async (promptName, conflictInfo) => {
30
34
  console.log(
31
35
  _chalk2.default.yellow(
@@ -48,8 +52,7 @@ var handleConflict = async (promptName, conflictInfo) => {
48
52
  console.log(" [l] Use local version (overwrite remote)");
49
53
  console.log(" [r] Use remote version (overwrite local)");
50
54
  console.log(" [a] Abort sync for this prompt");
51
- const readline = _chunkFJLK5CFLjs.__require.call(void 0, "readline");
52
- const rl = readline.createInterface({
55
+ const rl = _readline2.default.createInterface({
53
56
  input: process.stdin,
54
57
  output: process.stdout
55
58
  });
@@ -68,14 +71,14 @@ var handleConflict = async (promptName, conflictInfo) => {
68
71
  });
69
72
  };
70
73
  var syncCommand = async () => {
71
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
74
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
72
75
  const startTime = Date.now();
73
76
  try {
74
77
  _chunkF6E4XQQUjs.checkApiKey.call(void 0, );
75
- const promptService = _chunkVGHLQXKBjs.PromptService.getInstance();
76
- await _chunkHJU67C7Hjs.ensureProjectInitialized.call(void 0, false);
77
- const config = _chunk2JU376G7js.FileManager.loadPromptsConfig();
78
- const lock = _chunk2JU376G7js.FileManager.loadPromptsLock();
78
+ const langwatch = new (0, _chunk5EVBOHJYjs.LangWatch)();
79
+ await _chunkK64Y6YUGjs.ensureProjectInitialized.call(void 0, false);
80
+ const config = _chunkD2CSG4SJjs.FileManager.loadPromptsConfig();
81
+ const lock = _chunkD2CSG4SJjs.FileManager.loadPromptsLock();
79
82
  const result = {
80
83
  fetched: [],
81
84
  pushed: [],
@@ -100,14 +103,14 @@ var syncCommand = async () => {
100
103
  ).start();
101
104
  for (const [name, dependency] of remoteDeps) {
102
105
  try {
103
- const versionSpec = typeof dependency === "string" ? dependency : dependency.version || "latest";
106
+ const versionSpec = typeof dependency === "string" ? dependency : (_a = dependency.version) != null ? _a : "latest";
104
107
  const lockEntry = lock.prompts[name];
105
- const prompt = await promptService.get(name);
108
+ const prompt = await langwatch.prompts.get(name);
106
109
  if (prompt) {
107
110
  const needsUpdate = !lockEntry || lockEntry.version !== prompt.version || !lockEntry.materialized || !fs.existsSync(path.resolve(lockEntry.materialized));
108
111
  if (needsUpdate) {
109
- const materializedPrompt = _chunkSMXXAVMBjs.PromptConverter.fromApiToMaterialized(prompt);
110
- const savedPath = _chunk2JU376G7js.FileManager.saveMaterializedPrompt(
112
+ const materializedPrompt = _chunkSGNJDRCTjs.PromptConverter.fromApiToMaterialized(prompt);
113
+ const savedPath = _chunkD2CSG4SJjs.FileManager.saveMaterializedPrompt(
111
114
  name,
112
115
  materializedPrompt
113
116
  );
@@ -117,7 +120,7 @@ var syncCommand = async () => {
117
120
  version: prompt.version,
118
121
  versionSpec
119
122
  });
120
- _chunk2JU376G7js.FileManager.updateLockEntry(
123
+ _chunkD2CSG4SJjs.FileManager.updateLockEntry(
121
124
  lock,
122
125
  name,
123
126
  materializedPrompt,
@@ -153,20 +156,20 @@ var syncCommand = async () => {
153
156
  for (const [promptName, dependency] of localFileRefs) {
154
157
  try {
155
158
  const filePath = dependency.slice(5);
156
- const localConfig = _chunk2JU376G7js.FileManager.loadLocalPrompt(filePath);
157
- const currentVersion = (_a = lock.prompts[promptName]) == null ? void 0 : _a.version;
159
+ const localConfig = _chunkD2CSG4SJjs.FileManager.loadLocalPrompt(filePath);
160
+ const currentVersion = (_b = lock.prompts[promptName]) == null ? void 0 : _b.version;
158
161
  const configData = {
159
162
  model: localConfig.model,
160
- prompt: _chunkSMXXAVMBjs.PromptConverter.extractSystemPrompt(localConfig.messages),
161
- messages: _chunkSMXXAVMBjs.PromptConverter.filterNonSystemMessages(
163
+ prompt: _chunkSGNJDRCTjs.PromptConverter.extractSystemPrompt(localConfig.messages),
164
+ messages: _chunkSGNJDRCTjs.PromptConverter.filterNonSystemMessages(
162
165
  localConfig.messages
163
166
  ),
164
- temperature: (_b = localConfig.modelParameters) == null ? void 0 : _b.temperature,
165
- max_tokens: (_c = localConfig.modelParameters) == null ? void 0 : _c.max_tokens,
167
+ temperature: (_c = localConfig.modelParameters) == null ? void 0 : _c.temperature,
168
+ max_tokens: (_d = localConfig.modelParameters) == null ? void 0 : _d.max_tokens,
166
169
  inputs: [{ identifier: "input", type: "str" }],
167
170
  outputs: [{ identifier: "output", type: "str" }]
168
171
  };
169
- const syncResult = await promptService.sync({
172
+ const syncResult = await langwatch.prompts.sync({
170
173
  name: promptName,
171
174
  configData,
172
175
  localVersion: currentVersion,
@@ -199,7 +202,7 @@ var syncCommand = async () => {
199
202
  role: "system",
200
203
  content: syncResult.conflictInfo.remoteConfigData.prompt
201
204
  },
202
- ...(_d = syncResult.conflictInfo.remoteConfigData.messages) != null ? _d : []
205
+ ...(_e = syncResult.conflictInfo.remoteConfigData.messages) != null ? _e : []
203
206
  ]
204
207
  };
205
208
  const yamlContent = yaml.dump(remoteConfig, {
@@ -218,7 +221,7 @@ var syncCommand = async () => {
218
221
  materialized: filePath
219
222
  };
220
223
  } else if (syncResult.action === "conflict") {
221
- const remoteVersion = (_f = (_e = syncResult.conflictInfo) == null ? void 0 : _e.remoteVersion) != null ? _f : 0;
224
+ const remoteVersion = (_g = (_f = syncResult.conflictInfo) == null ? void 0 : _f.remoteVersion) != null ? _g : 0;
222
225
  if (conflictResolution === "remote") {
223
226
  lock.prompts[promptName] = {
224
227
  version: remoteVersion,
@@ -241,7 +244,7 @@ var syncCommand = async () => {
241
244
  actionText = "Pulled";
242
245
  result.fetched.push({
243
246
  name: promptName,
244
- version: ((_g = syncResult.conflictInfo) == null ? void 0 : _g.remoteVersion) || 0,
247
+ version: (_i = (_h = syncResult.conflictInfo) == null ? void 0 : _h.remoteVersion) != null ? _i : 0,
245
248
  versionSpec: "latest"
246
249
  // Default for conflict resolution
247
250
  });
@@ -249,7 +252,7 @@ var syncCommand = async () => {
249
252
  actionText = "Pushed";
250
253
  result.pushed.push({
251
254
  name: promptName,
252
- version: (((_h = syncResult.conflictInfo) == null ? void 0 : _h.remoteVersion) || 0) + 1
255
+ version: ((_k = (_j = syncResult.conflictInfo) == null ? void 0 : _j.remoteVersion) != null ? _k : 0) + 1
253
256
  // New version after push
254
257
  });
255
258
  }
@@ -257,19 +260,22 @@ var syncCommand = async () => {
257
260
  actionText = "Up-to-date";
258
261
  result.unchanged.push(promptName);
259
262
  } else {
260
- actionText = {
263
+ const actionMap = {
261
264
  created: "Created",
262
- updated: "Updated"
263
- }[syncResult.action] || "Pushed";
265
+ updated: "Updated",
266
+ conflict: "Conflict resolved",
267
+ up_to_date: "Up to date"
268
+ };
269
+ actionText = actionMap[syncResult.action] || "Pushed";
264
270
  result.pushed.push({
265
271
  name: promptName,
266
- version: ((_i = syncResult.prompt) == null ? void 0 : _i.version) || 0
272
+ version: (_m = (_l = syncResult.prompt) == null ? void 0 : _l.version) != null ? _m : 0
267
273
  });
268
274
  }
269
275
  pushSpinner.text = `${actionText} ${_chalk2.default.cyan(
270
276
  promptName
271
277
  )} ${_chalk2.default.gray(
272
- `(version ${((_j = syncResult.prompt) == null ? void 0 : _j.version) || ((_k = syncResult.conflictInfo) == null ? void 0 : _k.remoteVersion) || "unknown"})`
278
+ `(version ${(_q = (_p = (_n = syncResult.prompt) == null ? void 0 : _n.version) != null ? _p : (_o = syncResult.conflictInfo) == null ? void 0 : _o.remoteVersion) != null ? _q : "unknown"})`
273
279
  )} ${conflictResolution === "remote" ? "to" : "from"} ${_chalk2.default.gray(
274
280
  relativePath
275
281
  )}`;
@@ -278,12 +284,12 @@ var syncCommand = async () => {
278
284
  result.errors.push({ name: promptName, error: errorMessage });
279
285
  }
280
286
  }
281
- _chunk2JU376G7js.FileManager.savePromptsLock(lock);
287
+ _chunkD2CSG4SJjs.FileManager.savePromptsLock(lock);
282
288
  pushSpinner.stop();
283
289
  }
284
- const discoveredLocalFiles = _chunk2JU376G7js.FileManager.getLocalPromptFiles();
290
+ const discoveredLocalFiles = _chunkD2CSG4SJjs.FileManager.getLocalPromptFiles();
285
291
  const orphanFiles = discoveredLocalFiles.filter((filePath) => {
286
- const promptName = _chunk2JU376G7js.FileManager.promptNameFromPath(filePath);
292
+ const promptName = _chunkD2CSG4SJjs.FileManager.promptNameFromPath(filePath);
287
293
  return !config.prompts[promptName];
288
294
  });
289
295
  if (orphanFiles.length > 0) {
@@ -294,7 +300,7 @@ var syncCommand = async () => {
294
300
  )
295
301
  );
296
302
  for (const filePath of orphanFiles) {
297
- const promptName = _chunk2JU376G7js.FileManager.promptNameFromPath(filePath);
303
+ const promptName = _chunkD2CSG4SJjs.FileManager.promptNameFromPath(filePath);
298
304
  const relativePath = path.relative(process.cwd(), filePath);
299
305
  console.log(_chalk2.default.yellow(` ${relativePath}`));
300
306
  console.log(
@@ -322,12 +328,12 @@ Tip: Add these to prompts.json to include them in sync operations.`
322
328
  return true;
323
329
  })
324
330
  );
325
- const cleanedFiles = _chunk2JU376G7js.FileManager.cleanupOrphanedMaterializedFiles(currentDependencies);
331
+ const cleanedFiles = _chunkD2CSG4SJjs.FileManager.cleanupOrphanedMaterializedFiles(currentDependencies);
326
332
  if (cleanedFiles.length > 0) {
327
333
  result.cleaned = cleanedFiles;
328
- _chunk2JU376G7js.FileManager.removeFromLock(lock, cleanedFiles);
334
+ _chunkD2CSG4SJjs.FileManager.removeFromLock(lock, cleanedFiles);
329
335
  }
330
- _chunk2JU376G7js.FileManager.savePromptsLock(lock);
336
+ _chunkD2CSG4SJjs.FileManager.savePromptsLock(lock);
331
337
  if (result.fetched.length > 0) {
332
338
  for (const { name, version, versionSpec } of result.fetched) {
333
339
  const lockEntry = lock.prompts[name];
@@ -385,7 +391,7 @@ Tip: Add these to prompts.json to include them in sync operations.`
385
391
  process.exit(1);
386
392
  }
387
393
  } catch (error) {
388
- if (error instanceof _chunkVGHLQXKBjs.PromptsError) {
394
+ if (error instanceof _chunk4ZSSHX6Fjs.PromptsError) {
389
395
  console.error(_chalk2.default.red(`Error: ${error.message}`));
390
396
  } else {
391
397
  console.error(
@@ -400,4 +406,4 @@ Tip: Add these to prompts.json to include them in sync operations.`
400
406
 
401
407
 
402
408
  exports.syncCommand = syncCommand;
403
- //# sourceMappingURL=sync-EISKGPTL.js.map
409
+ //# sourceMappingURL=sync-PSU3F5Z4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/langwatch/langwatch/typescript-sdk/dist/sync-PSU3F5Z4.js","../src/cli/commands/sync.ts"],"names":[],"mappings":"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","file":"/home/runner/work/langwatch/langwatch/typescript-sdk/dist/sync-PSU3F5Z4.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 { type ConfigData, PromptsError, type SyncAction } from \"@/client-sdk/services/prompts\";\nimport { LangWatch } from \"@/client-sdk\";\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 `\\n⚠ Conflict detected for prompt: ${chalk.cyan(promptName)}`,\n ),\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 const startTime = Date.now();\n\n try {\n // Check API key before doing anything else\n checkApiKey();\n\n // Get LangWatch client\n const langwatch = new LangWatch();\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 langwatch.prompts.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 langwatch.prompts.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 - create new version (remote + 1)\n lock.prompts[promptName] = {\n version: remoteVersion + 1,\n versionId: \"conflict_resolved\", // Temporary until we get actual 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(`(version ${version})`)} 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"]}