@ryanfw/prompt-orchestration-pipeline 0.5.0 → 0.7.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 (67) hide show
  1. package/README.md +1 -2
  2. package/package.json +1 -2
  3. package/src/api/validators/json.js +39 -0
  4. package/src/components/DAGGrid.jsx +392 -303
  5. package/src/components/JobCard.jsx +14 -12
  6. package/src/components/JobDetail.jsx +54 -51
  7. package/src/components/JobTable.jsx +72 -23
  8. package/src/components/Layout.jsx +145 -42
  9. package/src/components/LiveText.jsx +47 -0
  10. package/src/components/PageSubheader.jsx +75 -0
  11. package/src/components/TaskDetailSidebar.jsx +216 -0
  12. package/src/components/TimerText.jsx +82 -0
  13. package/src/components/UploadSeed.jsx +0 -70
  14. package/src/components/ui/Logo.jsx +16 -0
  15. package/src/components/ui/RestartJobModal.jsx +140 -0
  16. package/src/components/ui/toast.jsx +138 -0
  17. package/src/config/models.js +322 -0
  18. package/src/config/statuses.js +119 -0
  19. package/src/core/config.js +4 -34
  20. package/src/core/file-io.js +13 -28
  21. package/src/core/module-loader.js +54 -40
  22. package/src/core/pipeline-runner.js +65 -26
  23. package/src/core/status-writer.js +213 -58
  24. package/src/core/symlink-bridge.js +57 -0
  25. package/src/core/symlink-utils.js +94 -0
  26. package/src/core/task-runner.js +321 -437
  27. package/src/llm/index.js +258 -86
  28. package/src/pages/Code.jsx +351 -0
  29. package/src/pages/PipelineDetail.jsx +124 -15
  30. package/src/pages/PromptPipelineDashboard.jsx +20 -88
  31. package/src/providers/anthropic.js +83 -69
  32. package/src/providers/base.js +52 -0
  33. package/src/providers/deepseek.js +20 -21
  34. package/src/providers/gemini.js +226 -0
  35. package/src/providers/openai.js +36 -106
  36. package/src/providers/zhipu.js +136 -0
  37. package/src/ui/client/adapters/job-adapter.js +42 -28
  38. package/src/ui/client/api.js +134 -0
  39. package/src/ui/client/hooks/useJobDetailWithUpdates.js +65 -179
  40. package/src/ui/client/index.css +15 -0
  41. package/src/ui/client/index.html +2 -1
  42. package/src/ui/client/main.jsx +19 -14
  43. package/src/ui/client/time-store.js +161 -0
  44. package/src/ui/config-bridge.js +15 -24
  45. package/src/ui/config-bridge.node.js +15 -24
  46. package/src/ui/dist/assets/{index-CxcrauYR.js → index-DqkbzXZ1.js} +2132 -1086
  47. package/src/ui/dist/assets/style-DBF9NQGk.css +62 -0
  48. package/src/ui/dist/index.html +4 -3
  49. package/src/ui/job-reader.js +0 -108
  50. package/src/ui/public/favicon.svg +12 -0
  51. package/src/ui/server.js +252 -0
  52. package/src/ui/sse-enhancer.js +0 -1
  53. package/src/ui/transformers/list-transformer.js +32 -12
  54. package/src/ui/transformers/status-transformer.js +29 -42
  55. package/src/utils/dag.js +8 -4
  56. package/src/utils/duration.js +13 -19
  57. package/src/utils/formatters.js +27 -0
  58. package/src/utils/geometry-equality.js +83 -0
  59. package/src/utils/pipelines.js +5 -1
  60. package/src/utils/time-utils.js +40 -0
  61. package/src/utils/token-cost-calculator.js +294 -0
  62. package/src/utils/ui.jsx +18 -20
  63. package/src/components/ui/select.jsx +0 -27
  64. package/src/lib/utils.js +0 -6
  65. package/src/ui/client/hooks/useTicker.js +0 -26
  66. package/src/ui/config-bridge.browser.js +0 -149
  67. package/src/ui/dist/assets/style-D6K_oQ12.css +0 -62
@@ -0,0 +1,94 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ /**
5
+ * Creates an idempotent symlink, safely handling existing files/symlinks.
6
+ *
7
+ * @param {string} linkPath - Path where the symlink should be created
8
+ * @param {string} targetPath - Path that the symlink should point to
9
+ * @param {'file' | 'dir'} type - Type of symlink to create
10
+ * @throws {Error} If symlink creation fails on non-POSIX systems
11
+ */
12
+ export async function ensureSymlink(linkPath, targetPath, type) {
13
+ try {
14
+ // Check if linkPath already exists
15
+ const stats = await fs.lstat(linkPath).catch(() => null);
16
+
17
+ if (stats) {
18
+ if (stats.isSymbolicLink()) {
19
+ // If it's already a symlink pointing to the correct target, we're done
20
+ const existingTarget = await fs.readlink(linkPath);
21
+ if (existingTarget === targetPath) {
22
+ return;
23
+ }
24
+ // If it points to a different target, remove it
25
+ await fs.unlink(linkPath);
26
+ } else if (stats.isDirectory()) {
27
+ // If it's a directory, remove it recursively
28
+ await fs.rmdir(linkPath, { recursive: true });
29
+ } else {
30
+ // If it's a file, remove it
31
+ await fs.unlink(linkPath);
32
+ }
33
+ }
34
+
35
+ // Ensure parent directory exists
36
+ const parentDir = path.dirname(linkPath);
37
+ await fs.mkdir(parentDir, { recursive: true });
38
+
39
+ // Create the symlink
40
+ await fs.symlink(targetPath, linkPath, type);
41
+ } catch (error) {
42
+ // Re-throw with more context
43
+ throw new Error(
44
+ `Failed to create symlink from ${linkPath} -> ${targetPath}: ${error.message}`
45
+ );
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Removes task symlinks from a completed job directory to avoid dangling links.
51
+ *
52
+ * @param {string} completedJobDir - Path to the completed job directory (e.g., COMPLETE_DIR/jobId)
53
+ */
54
+ export async function cleanupTaskSymlinks(completedJobDir) {
55
+ const tasksDir = path.join(completedJobDir, "tasks");
56
+
57
+ try {
58
+ // Check if tasks directory exists
59
+ const tasksStats = await fs.lstat(tasksDir).catch(() => null);
60
+ if (!tasksStats || !tasksStats.isDirectory()) {
61
+ return; // No tasks directory to clean up
62
+ }
63
+
64
+ // Get all task directories
65
+ const taskDirs = await fs.readdir(tasksDir, { withFileTypes: true });
66
+
67
+ for (const taskDir of taskDirs) {
68
+ if (!taskDir.isDirectory()) continue;
69
+
70
+ const taskPath = path.join(tasksDir, taskDir.name);
71
+
72
+ // Remove specific symlinks if they exist and are actually symlinks
73
+ const symlinksToRemove = ["node_modules", "project", "_task_root"];
74
+
75
+ for (const linkName of symlinksToRemove) {
76
+ const linkPath = path.join(taskPath, linkName);
77
+
78
+ try {
79
+ const stats = await fs.lstat(linkPath);
80
+ if (stats.isSymbolicLink()) {
81
+ await fs.unlink(linkPath);
82
+ }
83
+ } catch {
84
+ // Ignore errors (file doesn't exist, permissions, etc.)
85
+ }
86
+ }
87
+ }
88
+ } catch (error) {
89
+ // Log but don't fail - cleanup is optional
90
+ console.warn(
91
+ `Warning: Failed to cleanup task symlinks in ${completedJobDir}: ${error.message}`
92
+ );
93
+ }
94
+ }