vibe-coding-master 0.4.28 → 0.4.29

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.
@@ -0,0 +1,104 @@
1
+ import { isOpenFileLimitError, VcmError } from "../errors.js";
2
+ export function registerRuntimeStateRoutes(app, deps) {
3
+ app.get("/api/projects/runtime-state", async (request) => {
4
+ const project = await requireCurrentProject(deps.projectService);
5
+ const taskSlug = request.query.taskSlug?.trim();
6
+ const [translatorSession, translationState, harnessEngineerSession, harnessFeedbackState] = await Promise.all([
7
+ deps.sessionService.getProjectTranslatorSession(project.repoRoot).then((session) => session ?? null),
8
+ deps.translationWorkerService.getState(project.repoRoot, { visibility: "public" }),
9
+ deps.sessionService.getProjectHarnessEngineerSession(project.repoRoot).then((session) => session ?? null),
10
+ deps.harnessFeedbackService.getState(project.repoRoot, taskSlug || undefined)
11
+ ]);
12
+ if (!taskSlug) {
13
+ return {
14
+ translatorSession,
15
+ translationState,
16
+ harnessEngineerSession,
17
+ harnessStatus: null,
18
+ harnessBootstrapStatus: null,
19
+ harnessFeedbackState
20
+ };
21
+ }
22
+ try {
23
+ const task = await deps.taskService.loadTask(project.repoRoot, taskSlug);
24
+ const [harnessStatus, harnessBootstrapStatus] = await Promise.all([
25
+ withOpenFileLimitFallback(() => deps.harnessService.getHarnessStatus(task.worktreePath), (error) => degradedHarnessStatus(error)),
26
+ withOpenFileLimitFallback(() => deps.harnessService.getBootstrapStatus(project.repoRoot, task.worktreePath), (error) => degradedBootstrapStatus(error))
27
+ ]);
28
+ return {
29
+ translatorSession,
30
+ translationState,
31
+ harnessEngineerSession,
32
+ harnessStatus,
33
+ harnessBootstrapStatus,
34
+ harnessFeedbackState
35
+ };
36
+ }
37
+ catch (error) {
38
+ if (isOpenFileLimitError(error)) {
39
+ return {
40
+ translatorSession,
41
+ translationState,
42
+ harnessEngineerSession,
43
+ harnessStatus: degradedHarnessStatus(error),
44
+ harnessBootstrapStatus: degradedBootstrapStatus(error),
45
+ harnessFeedbackState
46
+ };
47
+ }
48
+ throw error;
49
+ }
50
+ });
51
+ }
52
+ async function requireCurrentProject(projectService) {
53
+ const project = await projectService.getCurrentProject();
54
+ if (!project) {
55
+ throw new VcmError({
56
+ code: "PROJECT_NOT_CONNECTED",
57
+ message: "Connect a repository first.",
58
+ statusCode: 409
59
+ });
60
+ }
61
+ return project;
62
+ }
63
+ function degradedHarnessStatus(error) {
64
+ return {
65
+ version: 1,
66
+ harnessRevision: 0,
67
+ initialized: false,
68
+ files: [],
69
+ needsApply: false,
70
+ plannedChanges: [],
71
+ warnings: [
72
+ `Harness status is temporarily unavailable because the backend hit the open-files limit: ${errorMessage(error)}`
73
+ ]
74
+ };
75
+ }
76
+ function degradedBootstrapStatus(error) {
77
+ return {
78
+ status: "not_ready",
79
+ canStart: false,
80
+ checks: [{
81
+ key: "fixed-harness",
82
+ label: "Fixed harness",
83
+ status: "unknown",
84
+ detail: `Backend open-files limit reached: ${errorMessage(error)}`
85
+ }],
86
+ warnings: [
87
+ `Harness bootstrap status is temporarily unavailable because the backend hit the open-files limit: ${errorMessage(error)}`
88
+ ]
89
+ };
90
+ }
91
+ async function withOpenFileLimitFallback(run, fallback) {
92
+ try {
93
+ return await run();
94
+ }
95
+ catch (error) {
96
+ if (isOpenFileLimitError(error)) {
97
+ return fallback(error);
98
+ }
99
+ throw error;
100
+ }
101
+ }
102
+ function errorMessage(error) {
103
+ return error instanceof Error ? error.message : String(error);
104
+ }
@@ -28,6 +28,61 @@ export function registerTaskRoutes(app, deps) {
28
28
  throw error;
29
29
  }
30
30
  });
31
+ app.get("/api/tasks/:taskSlug/workspace-state", async (request) => {
32
+ const taskSlug = request.params.taskSlug;
33
+ let repoRoot = "unknown";
34
+ try {
35
+ const project = await requireCurrentProject(deps.projectService);
36
+ repoRoot = project.repoRoot;
37
+ const config = await deps.projectService.loadConfig(project.repoRoot);
38
+ const task = await deps.taskService.loadTask(project.repoRoot, taskSlug);
39
+ const taskRepoRoot = getTaskRuntimeRepoRoot(task);
40
+ const context = {
41
+ repoRoot: project.repoRoot,
42
+ taskRepoRoot,
43
+ stateRepoRoot: taskRepoRoot,
44
+ stateRoot: config.stateRoot,
45
+ handoffDir: task.handoffDir,
46
+ taskSlug
47
+ };
48
+ const [taskStatus, messages, orchestration, roundState] = await Promise.all([
49
+ withOpenFileLimitFallback(() => deps.statusService.getTaskStatus(project.repoRoot, taskSlug), (error) => degradedTaskStatus(project.repoRoot, taskSlug, error)),
50
+ withOpenFileLimitFallback(() => deps.messageService.listMessages(context), () => []),
51
+ withOpenFileLimitFallback(() => deps.messageService.getOrchestrationState(context), () => ({
52
+ taskSlug,
53
+ mode: "auto",
54
+ updatedAt: new Date().toISOString()
55
+ })),
56
+ withOpenFileLimitFallback(() => deps.roundService.getSessionRoundState({
57
+ repoRoot: project.repoRoot,
58
+ stateRepoRoot: taskRepoRoot,
59
+ stateRoot: config.stateRoot,
60
+ taskSlug
61
+ }), () => degradedRoundState(taskSlug))
62
+ ]);
63
+ return {
64
+ taskStatus,
65
+ messages,
66
+ orchestration,
67
+ roundState
68
+ };
69
+ }
70
+ catch (error) {
71
+ if (isOpenFileLimitError(error)) {
72
+ return {
73
+ taskStatus: degradedTaskStatus(repoRoot, taskSlug, error),
74
+ messages: [],
75
+ orchestration: {
76
+ taskSlug,
77
+ mode: "auto",
78
+ updatedAt: new Date().toISOString()
79
+ },
80
+ roundState: degradedRoundState(taskSlug)
81
+ };
82
+ }
83
+ throw error;
84
+ }
85
+ });
31
86
  app.post("/api/tasks/:taskSlug/cleanup", async (request) => {
32
87
  const project = await requireCurrentProject(deps.projectService);
33
88
  const task = await deps.taskService.loadTask(project.repoRoot, request.params.taskSlug);
@@ -96,6 +151,32 @@ function degradedTaskStatus(repoRoot, taskSlug, error) {
96
151
  ]
97
152
  };
98
153
  }
154
+ function degradedRoundState(taskSlug) {
155
+ return {
156
+ taskSlug,
157
+ status: "stopped",
158
+ turnCount: 0,
159
+ completedTurnCount: 0,
160
+ totalRoundCount: 0,
161
+ totalTurnCount: 0,
162
+ totalCompletedTurnCount: 0,
163
+ totalCcActiveMs: 0,
164
+ currentRoundCcActiveMs: 0,
165
+ roles: [],
166
+ updatedAt: new Date().toISOString()
167
+ };
168
+ }
169
+ async function withOpenFileLimitFallback(run, fallback) {
170
+ try {
171
+ return await run();
172
+ }
173
+ catch (error) {
174
+ if (isOpenFileLimitError(error)) {
175
+ return fallback(error);
176
+ }
177
+ throw error;
178
+ }
179
+ }
99
180
  function degradedArtifactSummary(handoffDir) {
100
181
  const roleCommandsDir = `${handoffDir}/role-commands`;
101
182
  const messagesDir = `${handoffDir}/messages`;
@@ -41,6 +41,7 @@ import { registerHarnessRoutes } from "./api/harness-routes.js";
41
41
  import { registerMessageRoutes } from "./api/message-routes.js";
42
42
  import { registerProjectRoutes } from "./api/project-routes.js";
43
43
  import { registerRoundRoutes } from "./api/round-routes.js";
44
+ import { registerRuntimeStateRoutes } from "./api/runtime-state-routes.js";
44
45
  import { registerSessionRoutes } from "./api/session-routes.js";
45
46
  import { registerTaskRoutes } from "./api/task-routes.js";
46
47
  import { registerTranslationRoutes } from "./api/translation-routes.js";
@@ -90,11 +91,20 @@ export async function createServer(deps, options = {}) {
90
91
  sessionService: deps.sessionService,
91
92
  taskService: deps.taskService
92
93
  });
94
+ registerRuntimeStateRoutes(app, {
95
+ projectService: deps.projectService,
96
+ taskService: deps.taskService,
97
+ sessionService: deps.sessionService,
98
+ translationWorkerService: deps.translationWorkerService,
99
+ harnessService: deps.harnessService,
100
+ harnessFeedbackService: deps.harnessFeedbackService
101
+ });
93
102
  registerTaskRoutes(app, {
94
103
  projectService: deps.projectService,
95
104
  taskService: deps.taskService,
96
105
  sessionService: deps.sessionService,
97
106
  statusService: deps.statusService,
107
+ messageService: deps.messageService,
98
108
  translationService: deps.translationService,
99
109
  roundService: deps.roundService
100
110
  });