vibe64 0.1.21 → 0.1.22

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 (143) hide show
  1. package/dist/assets/ProjectTypeGate-B3NHteXC.js +1 -0
  2. package/dist/assets/ProjectTypeGate-fJcYj6sR.css +1 -0
  3. package/dist/assets/{SetupReadinessGate-DkkorR2Y.js → SetupReadinessGate-2twHjoYZ.js} +1 -1
  4. package/dist/assets/{ShellLayout-BcKS2HG9.js → ShellLayout-BjAbXfzf.js} +1 -1
  5. package/dist/assets/{VTabs-BJ8MKoig.js → VTabs-BLGGdbms.js} +1 -1
  6. package/dist/assets/{error-CwT53qTu.js → error-DvUPciuh.js} +1 -1
  7. package/dist/assets/history-DfM4ewyV.js +1 -0
  8. package/dist/assets/home-sh4v0vz7.js +1 -0
  9. package/dist/assets/index-C4JbNnml.css +1 -0
  10. package/dist/assets/{index-BJxDQvyK.js → index-CdFWokfE.js} +1 -1
  11. package/dist/assets/index-D4oqjV9n.js +132 -0
  12. package/dist/assets/{index-CY-wDjNv.js → index-DqoYKexs.js} +15 -15
  13. package/dist/assets/{placement-7FCYadh2.js → placement-QfRaYTFY.js} +1 -1
  14. package/dist/assets/{setup-BzzdD38G.js → setup-B-WOti3H.js} +2 -2
  15. package/dist/assets/{streamEvents-Ba9kHw-1.js → streamEvents-CIqegoLa.js} +1 -1
  16. package/dist/assets/{studioGateApi-hkZdLr1Y.js → studioGateApi-CFtez6lH.js} +1 -1
  17. package/dist/assets/{target-scripts-8hczu84t.js → target-scripts-CI-nAISO.js} +1 -1
  18. package/dist/assets/useStudioTerminal-I8tuBymw.js +1 -0
  19. package/dist/assets/vibe64SessionPanelModel-DLdexNxC.js +1 -0
  20. package/dist/index.html +1 -1
  21. package/node_modules/@local/setup-doctor-core/src/server/doctorToolchain.js +4 -0
  22. package/node_modules/@local/studio-terminal-core/src/server/gitGithubTransport.js +33 -0
  23. package/node_modules/@local/studio-terminal-core/src/server/index.js +1 -0
  24. package/node_modules/@local/studio-terminal-core/src/server/terminalSessions.js +51 -1
  25. package/node_modules/@local/vibe64-adapters/src/server/adapter.js +4 -0
  26. package/node_modules/@local/vibe64-adapters/src/server/adapters/laravel/adapter.js +5 -0
  27. package/node_modules/@local/vibe64-adapters/src/server/adapters/laravel/databaseRuntime.js +50 -0
  28. package/node_modules/@local/vibe64-adapters/src/server/configStore.js +22 -1
  29. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/agent_conversation.txt +0 -2
  30. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/draft_issue.txt +18 -0
  31. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/make_plan.txt +14 -2
  32. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/prepare_for_merge.txt +2 -0
  33. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/resolve_pull_request.txt +1 -0
  34. package/node_modules/@local/vibe64-adapters/src/server/systemPrompts/run_deep_ui_check.txt +7 -3
  35. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/commitPush.js +4 -22
  36. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/factMetadata.js +21 -20
  37. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/issuePr.js +27 -4
  38. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/mergeSync.js +65 -8
  39. package/node_modules/@local/vibe64-adapters/src/server/workflowCommandTerminal/worktreeDependencies.js +12 -25
  40. package/node_modules/@local/vibe64-adapters/src/server/workflowSessionActions.js +77 -20
  41. package/node_modules/@local/vibe64-core/src/server/terminalWebSocketRoutes.js +14 -5
  42. package/node_modules/@local/vibe64-project/src/server/actions.js +21 -0
  43. package/node_modules/@local/vibe64-project/src/server/registerRoutes.js +6 -0
  44. package/node_modules/@local/vibe64-project/src/server/service.js +125 -8
  45. package/node_modules/@local/vibe64-runtime/src/server/coreProjectTools.js +135 -0
  46. package/node_modules/@local/vibe64-runtime/src/server/index.js +4 -0
  47. package/node_modules/@local/vibe64-runtime/src/server/projectToolRegistry.js +434 -0
  48. package/node_modules/@local/vibe64-runtime/src/server/runtime.js +40 -16
  49. package/node_modules/@local/vibe64-runtime/src/server/sessionWorktreeState.js +25 -0
  50. package/node_modules/@local/vibe64-runtime/src/server/terminalFailureFixRequest.js +112 -0
  51. package/node_modules/@local/vibe64-runtime/src/server/workflowArtifacts.js +2 -2
  52. package/node_modules/@local/vibe64-runtime/src/server/workflowDefinitionBuilders.js +1 -0
  53. package/node_modules/@local/vibe64-runtime/src/server/workflowDefinitionComposers.js +192 -0
  54. package/node_modules/@local/vibe64-runtime/src/server/workflowMachine.js +5 -0
  55. package/node_modules/@local/vibe64-runtime/src/server/workflowModules/coreCoding.js +1309 -419
  56. package/node_modules/@local/vibe64-runtime/src/server/workflowModules/coreLifecycle.js +540 -358
  57. package/node_modules/@local/vibe64-runtime/src/server/workflowModules/coreMaintenance.js +5 -26
  58. package/node_modules/@local/vibe64-runtime/src/server/workflowPresentation.js +153 -26
  59. package/node_modules/@local/vibe64-runtime/src/server/workflowStepMachineHelpers.js +63 -10
  60. package/node_modules/@local/vibe64-runtime/src/server/workflowStepMachines.js +63 -2
  61. package/node_modules/@local/vibe64-sessions/src/server/inputSchemas.js +5 -0
  62. package/node_modules/@local/vibe64-sessions/src/server/service.js +8 -9
  63. package/node_modules/@local/vibe64-terminals/src/server/actions.js +65 -0
  64. package/node_modules/@local/vibe64-terminals/src/server/codexTerminal.js +608 -23
  65. package/node_modules/@local/vibe64-terminals/src/server/commandTerminal.js +261 -4
  66. package/node_modules/@local/vibe64-terminals/src/server/fixCodexJobs.js +420 -0
  67. package/node_modules/@local/vibe64-terminals/src/server/inputSchemas.js +240 -0
  68. package/node_modules/@local/vibe64-terminals/src/server/launchTargetTerminal.js +2 -0
  69. package/node_modules/@local/vibe64-terminals/src/server/registerRoutes.js +226 -0
  70. package/node_modules/@local/vibe64-terminals/src/server/service.js +140 -1
  71. package/node_modules/@local/vibe64-terminals/src/server/targetToolchainTerminal.js +1 -1
  72. package/node_modules/@local/vibe64-terminals/src/server/terminalShared.js +34 -0
  73. package/node_modules/node-pty/build/Makefile +369 -0
  74. package/node_modules/node-pty/build/Release/pty.node +0 -0
  75. package/node_modules/node-pty/build/binding.Makefile +6 -0
  76. package/node_modules/node-pty/build/config.gypi +440 -0
  77. package/node_modules/node-pty/build/pty.target.mk +166 -0
  78. package/node_modules/node-pty/node-addon-api/node_addon_api.Makefile +6 -0
  79. package/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +104 -0
  80. package/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +108 -0
  81. package/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +104 -0
  82. package/node_modules/which/CHANGELOG.md +166 -0
  83. package/package.json +2 -2
  84. package/packages/setup-doctor-core/src/server/doctorToolchain.js +4 -0
  85. package/packages/studio-terminal-core/src/server/gitGithubTransport.js +33 -0
  86. package/packages/studio-terminal-core/src/server/index.js +1 -0
  87. package/packages/studio-terminal-core/src/server/terminalSessions.js +51 -1
  88. package/packages/vibe64-adapters/src/server/adapter.js +4 -0
  89. package/packages/vibe64-adapters/src/server/adapters/laravel/adapter.js +5 -0
  90. package/packages/vibe64-adapters/src/server/adapters/laravel/databaseRuntime.js +50 -0
  91. package/packages/vibe64-adapters/src/server/configStore.js +22 -1
  92. package/packages/vibe64-adapters/src/server/systemPrompts/agent_conversation.txt +0 -2
  93. package/packages/vibe64-adapters/src/server/systemPrompts/draft_issue.txt +18 -0
  94. package/packages/vibe64-adapters/src/server/systemPrompts/make_plan.txt +14 -2
  95. package/packages/vibe64-adapters/src/server/systemPrompts/prepare_for_merge.txt +2 -0
  96. package/packages/vibe64-adapters/src/server/systemPrompts/resolve_pull_request.txt +1 -0
  97. package/packages/vibe64-adapters/src/server/systemPrompts/run_deep_ui_check.txt +7 -3
  98. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/commitPush.js +4 -22
  99. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/factMetadata.js +21 -20
  100. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/issuePr.js +27 -4
  101. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/mergeSync.js +65 -8
  102. package/packages/vibe64-adapters/src/server/workflowCommandTerminal/worktreeDependencies.js +12 -25
  103. package/packages/vibe64-adapters/src/server/workflowSessionActions.js +77 -20
  104. package/packages/vibe64-core/src/server/terminalWebSocketRoutes.js +14 -5
  105. package/packages/vibe64-project/src/server/actions.js +21 -0
  106. package/packages/vibe64-project/src/server/registerRoutes.js +6 -0
  107. package/packages/vibe64-project/src/server/service.js +125 -8
  108. package/packages/vibe64-runtime/src/server/coreProjectTools.js +135 -0
  109. package/packages/vibe64-runtime/src/server/index.js +4 -0
  110. package/packages/vibe64-runtime/src/server/projectToolRegistry.js +434 -0
  111. package/packages/vibe64-runtime/src/server/runtime.js +40 -16
  112. package/packages/vibe64-runtime/src/server/sessionWorktreeState.js +25 -0
  113. package/packages/vibe64-runtime/src/server/terminalFailureFixRequest.js +112 -0
  114. package/packages/vibe64-runtime/src/server/workflowArtifacts.js +2 -2
  115. package/packages/vibe64-runtime/src/server/workflowDefinitionBuilders.js +1 -0
  116. package/packages/vibe64-runtime/src/server/workflowDefinitionComposers.js +192 -0
  117. package/packages/vibe64-runtime/src/server/workflowMachine.js +5 -0
  118. package/packages/vibe64-runtime/src/server/workflowModules/coreCoding.js +1309 -419
  119. package/packages/vibe64-runtime/src/server/workflowModules/coreLifecycle.js +540 -358
  120. package/packages/vibe64-runtime/src/server/workflowModules/coreMaintenance.js +5 -26
  121. package/packages/vibe64-runtime/src/server/workflowPresentation.js +153 -26
  122. package/packages/vibe64-runtime/src/server/workflowStepMachineHelpers.js +63 -10
  123. package/packages/vibe64-runtime/src/server/workflowStepMachines.js +63 -2
  124. package/packages/vibe64-sessions/src/server/inputSchemas.js +5 -0
  125. package/packages/vibe64-sessions/src/server/service.js +8 -9
  126. package/packages/vibe64-terminals/src/server/actions.js +65 -0
  127. package/packages/vibe64-terminals/src/server/codexTerminal.js +608 -23
  128. package/packages/vibe64-terminals/src/server/commandTerminal.js +261 -4
  129. package/packages/vibe64-terminals/src/server/fixCodexJobs.js +420 -0
  130. package/packages/vibe64-terminals/src/server/inputSchemas.js +240 -0
  131. package/packages/vibe64-terminals/src/server/launchTargetTerminal.js +2 -0
  132. package/packages/vibe64-terminals/src/server/registerRoutes.js +226 -0
  133. package/packages/vibe64-terminals/src/server/service.js +140 -1
  134. package/packages/vibe64-terminals/src/server/targetToolchainTerminal.js +1 -1
  135. package/packages/vibe64-terminals/src/server/terminalShared.js +34 -0
  136. package/dist/assets/ProjectTypeGate-DStq4W4X.js +0 -1
  137. package/dist/assets/ProjectTypeGate-Dh2ycSoM.css +0 -1
  138. package/dist/assets/history-HQ_XliX2.js +0 -1
  139. package/dist/assets/home-B89EbUmA.js +0 -1
  140. package/dist/assets/index-16P0GeGq.js +0 -134
  141. package/dist/assets/index-eMhOXhf_.css +0 -1
  142. package/dist/assets/useStudioTerminal-D9TNb50w.js +0 -1
  143. package/dist/assets/vibe64SessionPanelModel-DvY_IbW3.js +0 -1
@@ -57,12 +57,11 @@ function createWorktreeScript({
57
57
  const quotedPrepareWorktreeScriptPath = shellQuote(normalizeText(prepareWorktreeScriptPath));
58
58
  const quotedTargetRoot = shellQuote(targetRoot);
59
59
  const quotedWorktreePath = shellQuote(worktreePath);
60
- const workSource = normalizeText(session.metadata?.work_source) || "new_branch";
60
+ const workSource = normalizeText(session.metadata?.work_source) || "new_issue";
61
61
  const sourcePrNumber = normalizeText(session.metadata?.source_pr_number);
62
62
  const sourcePrHeadRef = normalizeText(session.metadata?.source_pr_head_ref);
63
63
  const sourcePrHeadRepo = normalizeText(session.metadata?.source_pr_head_repo);
64
- const sourcePrUrl = normalizeText(session.metadata?.source_pr_url);
65
- const requestedUpdateMode = normalizeText(session.metadata?.source_pr_update_mode);
64
+ const sourcePrHeadSha = normalizeText(session.metadata?.source_pr_head_sha);
66
65
  return [
67
66
  "set -e",
68
67
  `export VIBE64_TARGET_ROOT=${quotedTargetRoot}`,
@@ -92,8 +91,7 @@ function createWorktreeScript({
92
91
  `SOURCE_PR_NUMBER=${shellQuote(sourcePrNumber)}`,
93
92
  `SOURCE_PR_HEAD_REF=${shellQuote(sourcePrHeadRef)}`,
94
93
  `SOURCE_PR_HEAD_REPO=${shellQuote(sourcePrHeadRepo)}`,
95
- `SOURCE_PR_URL=${shellQuote(sourcePrUrl)}`,
96
- `REQUESTED_UPDATE_MODE=${shellQuote(requestedUpdateMode)}`,
94
+ `SOURCE_PR_HEAD_SHA=${shellQuote(sourcePrHeadSha)}`,
97
95
  "if [ -z \"$SOURCE_PR_NUMBER\" ]; then",
98
96
  " printf '[studio] Existing PR metadata is incomplete. Abandon this session and start again.\\n' >&2",
99
97
  " exit 1",
@@ -101,30 +99,19 @@ function createWorktreeScript({
101
99
  "PR_FETCH_REF=\"refs/remotes/vibe64/pr/$SOURCE_PR_NUMBER\"",
102
100
  "printf '[studio] Fetching PR #%s\\n' \"$SOURCE_PR_NUMBER\"",
103
101
  `git -C ${quotedTargetRoot} fetch origin "pull/$SOURCE_PR_NUMBER/head:$PR_FETCH_REF"`,
102
+ "FETCHED_PR_SHA=\"$(git -C " + quotedTargetRoot + " rev-parse --verify \"$PR_FETCH_REF\")\"",
103
+ "if [ -n \"$SOURCE_PR_HEAD_SHA\" ] && [ \"$FETCHED_PR_SHA\" != \"$SOURCE_PR_HEAD_SHA\" ]; then",
104
+ " printf '[studio] Existing PR #%s moved from %s to %s. Start a new session from the updated PR.\\n' \"$SOURCE_PR_NUMBER\" \"$SOURCE_PR_HEAD_SHA\" \"$FETCHED_PR_SHA\" >&2",
105
+ " exit 1",
106
+ "fi",
104
107
  `if git -C ${quotedTargetRoot} show-ref --verify --quiet ${quotedBranchRef}; then`,
105
108
  ` git -C ${quotedTargetRoot} worktree add ${quotedWorktreePath} ${quotedBranch}`,
106
109
  "else",
107
110
  ` git -C ${quotedTargetRoot} worktree add -b ${quotedBranch} ${quotedWorktreePath} "$PR_FETCH_REF"`,
108
111
  "fi",
109
112
  "prepare_vibe64_worktree",
110
- "if [ \"$REQUESTED_UPDATE_MODE\" = \"direct\" ]; then",
111
- " if [ -z \"$SOURCE_PR_HEAD_REF\" ] || [ -z \"$SOURCE_PR_HEAD_REPO\" ]; then",
112
- " printf '[studio] Existing PR push target is incomplete; this session will create a replacement PR.\\n'",
113
- ` ${recordCommandFactScript("source_pr_update_mode", "replacement")}`,
114
- " exit 0",
115
- " fi",
116
- " PR_HEAD_REMOTE=\"vibe64-pr-head\"",
117
- ` git -C ${quotedWorktreePath} remote remove "$PR_HEAD_REMOTE" >/dev/null 2>&1 || true`,
118
- ` git -C ${quotedWorktreePath} remote add "$PR_HEAD_REMOTE" "https://github.com/$SOURCE_PR_HEAD_REPO.git"`,
119
- ` if git -C ${quotedWorktreePath} push --dry-run "$PR_HEAD_REMOTE" "HEAD:refs/heads/$SOURCE_PR_HEAD_REF"; then`,
120
- " printf '[studio] Existing PR can be updated directly.\\n'",
121
- ` ${recordCommandFactScript("source_pr_update_mode", "direct")}`,
122
- ` ${recordCommandFactScript("pr_url", "\"$SOURCE_PR_URL\"")}`,
123
- " else",
124
- " printf '[studio] Existing PR cannot be pushed directly; this session will create a replacement PR.\\n'",
125
- ` ${recordCommandFactScript("source_pr_update_mode", "replacement")}`,
126
- " fi",
127
- "fi",
113
+ "printf '[studio] Session branch will stack on existing PR branch %s/%s.\\n' \"$SOURCE_PR_HEAD_REPO\" \"$SOURCE_PR_HEAD_REF\"",
114
+ recordCommandFactScript("source_pr_update_mode", "stacked"),
128
115
  "exit 0"
129
116
  ] : []),
130
117
  `if git -C ${quotedTargetRoot} show-ref --verify --quiet ${quotedBranchRef}; then`,
@@ -154,9 +141,9 @@ async function createWorktreeTerminalSpec({
154
141
  readCurrentBranch(resolvedTargetRoot),
155
142
  readCurrentCommit(resolvedTargetRoot)
156
143
  ]);
157
- const workSource = normalizeText(session.metadata?.work_source) || "new_branch";
144
+ const workSource = normalizeText(session.metadata?.work_source) || "new_issue";
158
145
  const metadataBaseBranch = workSource === "existing_pr"
159
- ? normalizeText(session.metadata?.source_pr_base_ref) || baseBranch
146
+ ? normalizeText(session.metadata?.source_pr_head_ref) || baseBranch
160
147
  : baseBranch;
161
148
  const metadataBaseCommit = workSource === "existing_pr"
162
149
  ? normalizeText(session.metadata?.source_pr_head_sha) || baseCommit
@@ -12,6 +12,9 @@ import {
12
12
  const execFileAsync = promisify(execFile);
13
13
  const GITHUB_COMMAND_TIMEOUT_MS = 30_000;
14
14
  const GITHUB_OUTPUT_BUFFER_BYTES = 1024 * 1024;
15
+ const ISSUE_BODY_ARTIFACT = "issue.md";
16
+ const ISSUE_TITLE_ARTIFACT = "issue_title";
17
+ const ISSUE_WORD_ARTIFACT = "issue_word";
15
18
 
16
19
  function commandOutput(error = {}) {
17
20
  return normalizeText(`${error.stdout || ""}\n${error.stderr || ""}`) ||
@@ -22,6 +25,20 @@ function normalizeGithubNumberOrUrl(value = "") {
22
25
  return normalizeText(value).replace(/^#/u, "");
23
26
  }
24
27
 
28
+ function artifactText(value = "") {
29
+ const text = normalizeText(value);
30
+ return text ? `${text}\n` : "";
31
+ }
32
+
33
+ function issueWordFromGithubIssue(issue = {}, issueRef = "") {
34
+ const candidate = normalizeText(issue.title)
35
+ .split(/\s+/u)
36
+ .map((word) => word.replace(/[^A-Za-z0-9_-]+/gu, ""))
37
+ .find(Boolean);
38
+ const fallback = `issue${normalizeText(issue.number) || normalizeText(issueRef) || "selected"}`;
39
+ return normalizeText(candidate || fallback).slice(0, 24);
40
+ }
41
+
25
42
  async function ghJson(targetRoot, args = []) {
26
43
  try {
27
44
  const result = await execFileAsync("gh", args, {
@@ -48,21 +65,33 @@ function repositoryNameWithOwner(repository = {}) {
48
65
  normalizeText(repository.url).replace(/^https:\/\/github\.com\//u, "");
49
66
  }
50
67
 
51
- function prCanUseDirectUpdate(pr = {}) {
52
- if (normalizeText(pr.state).toUpperCase() !== "OPEN") {
53
- return false;
54
- }
55
- if (!normalizeText(pr.headRefName) || !repositoryNameWithOwner(pr.headRepository)) {
56
- return false;
57
- }
58
- return pr.isCrossRepository !== true || pr.maintainerCanModify === true;
68
+ function prCanUseStackedBase(pr = {}) {
69
+ return normalizeText(pr.state).toUpperCase() === "OPEN" &&
70
+ normalizeText(pr.headRefName) &&
71
+ normalizeText(pr.headRefOid) &&
72
+ pr.isCrossRepository === false;
59
73
  }
60
74
 
61
- async function useNewBranchSessionAction() {
75
+ async function useNewIssueSessionAction() {
62
76
  return adapterActionResult({
63
- message: "Selected a new Vibe64 branch.",
77
+ message: "Starting fresh with a new GitHub issue.",
64
78
  metadata: {
65
- work_source: "new_branch"
79
+ github_issue_mode: "create",
80
+ issue_source: "new",
81
+ work_anchor_type: "issue",
82
+ work_source: "new_issue"
83
+ }
84
+ });
85
+ }
86
+
87
+ async function useDescriptionSessionAction() {
88
+ return adapterActionResult({
89
+ message: "Starting from a plain work description.",
90
+ metadata: {
91
+ github_issue_mode: "skip",
92
+ issue_source: "none",
93
+ work_anchor_type: "description",
94
+ work_source: "description"
66
95
  }
67
96
  });
68
97
  }
@@ -93,7 +122,7 @@ async function useExistingIssueSessionAction({
93
122
  "view",
94
123
  issueRef,
95
124
  "--json",
96
- "number,title,url,state"
125
+ "number,title,url,state,body"
97
126
  ]);
98
127
  if (result.ok === false) {
99
128
  return adapterActionResult({
@@ -109,13 +138,28 @@ async function useExistingIssueSessionAction({
109
138
  status: "blocked"
110
139
  });
111
140
  }
141
+ const title = normalizeText(issue.title);
142
+ const body = normalizeText(issue.body) || title;
143
+ const word = issueWordFromGithubIssue(issue, issueRef);
112
144
  return adapterActionResult({
113
- message: `Selected GitHub issue #${issue.number}: ${normalizeText(issue.title)}`,
145
+ artifacts: {
146
+ [ISSUE_BODY_ARTIFACT]: artifactText(body),
147
+ [ISSUE_TITLE_ARTIFACT]: artifactText(title),
148
+ [ISSUE_WORD_ARTIFACT]: artifactText(word)
149
+ },
150
+ message: `Selected GitHub issue #${issue.number}: ${title}`,
114
151
  metadata: {
152
+ github_issue_mode: "reuse",
115
153
  issue_number: String(issue.number || ""),
116
154
  issue_source: "existing",
117
- issue_title: normalizeText(issue.title),
118
- issue_url: normalizeText(issue.url)
155
+ issue_title: title,
156
+ issue_url: normalizeText(issue.url),
157
+ work_anchor_number: String(issue.number || ""),
158
+ work_anchor_title: title,
159
+ work_anchor_type: "issue",
160
+ work_anchor_url: normalizeText(issue.url),
161
+ work_source: "existing_issue",
162
+ [ISSUE_WORD_ARTIFACT]: word
119
163
  }
120
164
  });
121
165
  }
@@ -165,10 +209,18 @@ async function useExistingPrSessionAction({
165
209
  status: "blocked"
166
210
  });
167
211
  }
168
- const updateMode = prCanUseDirectUpdate(pr) ? "direct" : "replacement";
212
+ if (!prCanUseStackedBase(pr)) {
213
+ return adapterActionResult({
214
+ message: `GitHub PR #${pr.number || prRef} cannot be used as a stacked PR base because its head branch is not in this repository.`,
215
+ status: "blocked"
216
+ });
217
+ }
218
+ const title = normalizeText(pr.title);
169
219
  return adapterActionResult({
170
- message: `Selected GitHub PR #${pr.number}: ${normalizeText(pr.title)}`,
220
+ message: `Selected GitHub PR #${pr.number}: ${title}`,
171
221
  metadata: {
222
+ github_issue_mode: "skip",
223
+ issue_source: "none",
172
224
  source_pr_base_ref: normalizeText(pr.baseRefName),
173
225
  source_pr_head_ref: normalizeText(pr.headRefName),
174
226
  source_pr_head_repo: repositoryNameWithOwner(pr.headRepository),
@@ -177,9 +229,13 @@ async function useExistingPrSessionAction({
177
229
  source_pr_maintainer_can_modify: pr.maintainerCanModify === true ? "yes" : "no",
178
230
  source_pr_number: String(pr.number || ""),
179
231
  source_pr_state: normalizeText(pr.state),
180
- source_pr_title: normalizeText(pr.title),
181
- source_pr_update_mode: updateMode,
232
+ source_pr_title: title,
233
+ source_pr_update_mode: "stacked",
182
234
  source_pr_url: normalizeText(pr.url),
235
+ work_anchor_number: String(pr.number || ""),
236
+ work_anchor_title: title,
237
+ work_anchor_type: "pull_request",
238
+ work_anchor_url: normalizeText(pr.url),
183
239
  work_source: "existing_pr"
184
240
  }
185
241
  });
@@ -187,9 +243,10 @@ async function useExistingPrSessionAction({
187
243
 
188
244
  const VIBE64_WORKFLOW_SESSION_ACTIONS = Object.freeze({
189
245
  skip_merge: skipMergeSessionAction,
246
+ use_description: useDescriptionSessionAction,
190
247
  use_existing_issue: useExistingIssueSessionAction,
191
248
  use_existing_pr: useExistingPrSessionAction,
192
- use_new_branch: useNewBranchSessionAction
249
+ use_new_issue: useNewIssueSessionAction
193
250
  });
194
251
 
195
252
  async function runVibe64WorkflowSessionAction(actionId, context = {}) {
@@ -83,8 +83,11 @@ function registerTerminalWebSocketRoute(
83
83
  closeWithError(1011, String(error?.message || error || serviceUnavailableMessage));
84
84
  return;
85
85
  }
86
- const sessionId = String(request.params?.sessionId || "");
87
- const terminalSessionId = String(request.params?.terminalSessionId || "");
86
+ const routeParams = request.params || {};
87
+ const sessionId = String(routeParams.sessionId || "");
88
+ const terminalSessionId = String(routeParams.terminalSessionId || "");
89
+ const toolId = String(routeParams.toolId || "");
90
+ const jobId = String(routeParams.jobId || "");
88
91
 
89
92
  socket.on("message", async (rawMessage) => {
90
93
  try {
@@ -92,8 +95,10 @@ function registerTerminalWebSocketRoute(
92
95
  if (message?.type === "input") {
93
96
  const response = await write(service, {
94
97
  data: message.data,
98
+ jobId,
95
99
  sessionId,
96
- terminalSessionId
100
+ terminalSessionId,
101
+ toolId
97
102
  });
98
103
  if (response?.ok === false) {
99
104
  sendSocketJson(socket, {
@@ -106,9 +111,11 @@ function registerTerminalWebSocketRoute(
106
111
  if (message?.type === "resize") {
107
112
  const response = await resize?.(service, {
108
113
  cols: message.cols,
114
+ jobId,
109
115
  rows: message.rows,
110
116
  sessionId,
111
- terminalSessionId
117
+ terminalSessionId,
118
+ toolId
112
119
  });
113
120
  if (response?.ok === false) {
114
121
  sendSocketJson(socket, {
@@ -129,11 +136,13 @@ function registerTerminalWebSocketRoute(
129
136
  socket.on("error", closeSubscription);
130
137
 
131
138
  void Promise.resolve(subscribe(service, {
139
+ jobId,
132
140
  sessionId,
133
141
  subscriber: (message) => {
134
142
  sendSocketJson(socket, message);
135
143
  },
136
- terminalSessionId
144
+ terminalSessionId,
145
+ toolId
137
146
  })).then((result) => {
138
147
  if (result?.ok === false) {
139
148
  closeWithError(1008, result.error || "Terminal session not found.");
@@ -5,6 +5,7 @@ import {
5
5
  projectTypeReadInputValidator
6
6
  } from "./inputSchemas.js";
7
7
 
8
+ const ACTION_LIST_PROJECT_TOOLS = "feature.vibe64-project.tools.list";
8
9
  const ACTION_READ_PROJECT_TYPE = "feature.vibe64-project.project-type.read";
9
10
  const ACTION_SAVE_PROJECT_TYPE = "feature.vibe64-project.project-type.save";
10
11
  const ACTION_READ_PROJECT_CONFIG = "feature.vibe64-project.config.read";
@@ -12,6 +13,25 @@ const ACTION_READ_PROJECT_CONFIG_DEFAULTS = "feature.vibe64-project.config.defau
12
13
  const ACTION_SAVE_PROJECT_CONFIG = "feature.vibe64-project.config.save";
13
14
 
14
15
  const featureActions = Object.freeze([
16
+ {
17
+ id: ACTION_LIST_PROJECT_TOOLS,
18
+ version: 1,
19
+ kind: "query",
20
+ channels: ["api", "automation", "internal"],
21
+ surfaces: ["home"],
22
+ input: projectConfigReadInputValidator,
23
+ output: null,
24
+ idempotency: "none",
25
+ audit: {
26
+ actionName: ACTION_LIST_PROJECT_TOOLS
27
+ },
28
+ observability: {},
29
+ async execute(input, context, deps) {
30
+ void input;
31
+ void context;
32
+ return deps.featureService.listProjectTools();
33
+ }
34
+ },
15
35
  {
16
36
  id: ACTION_READ_PROJECT_TYPE,
17
37
  version: 1,
@@ -108,6 +128,7 @@ const featureActions = Object.freeze([
108
128
  ]);
109
129
 
110
130
  export {
131
+ ACTION_LIST_PROJECT_TOOLS,
111
132
  ACTION_READ_PROJECT_CONFIG,
112
133
  ACTION_READ_PROJECT_CONFIG_DEFAULTS,
113
134
  ACTION_READ_PROJECT_TYPE,
@@ -3,6 +3,7 @@ import {
3
3
  projectTypeInputValidator
4
4
  } from "./inputSchemas.js";
5
5
  import {
6
+ ACTION_LIST_PROJECT_TOOLS,
6
7
  ACTION_READ_PROJECT_CONFIG,
7
8
  ACTION_READ_PROJECT_CONFIG_DEFAULTS,
8
9
  ACTION_READ_PROJECT_TYPE,
@@ -25,6 +26,11 @@ function registerRoutes(
25
26
  tags: ["studio", "vibe64-project"]
26
27
  });
27
28
 
29
+ routes.actionRoute("GET", "/tools", {
30
+ actionId: ACTION_LIST_PROJECT_TOOLS,
31
+ summary: "List Vibe64 project tools."
32
+ });
33
+
28
34
  routes.actionRoute("GET", "/project-type", {
29
35
  actionId: ACTION_READ_PROJECT_TYPE,
30
36
  summary: "Read the Vibe64 project type."
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  Vibe64SessionRuntime
3
3
  } from "@local/vibe64-runtime/server/runtime";
4
+ import {
5
+ createCoreProjectToolRegistry
6
+ } from "@local/vibe64-runtime/server/coreProjectTools";
4
7
  import {
5
8
  createCoreWorkflowRegistry
6
9
  } from "@local/vibe64-runtime/server/registerCoreWorkflowModules";
@@ -138,11 +141,11 @@ function createService({
138
141
  };
139
142
  }
140
143
 
141
- function configResponse({
142
- adapter,
143
- config,
144
- projectType
145
- } = {}) {
144
+ function configResponse({
145
+ adapter,
146
+ config,
147
+ projectType
148
+ } = {}) {
146
149
  return {
147
150
  ...config,
148
151
  adapter: {
@@ -153,6 +156,102 @@ function createService({
153
156
  };
154
157
  }
155
158
 
159
+ async function projectToolContext() {
160
+ const projectType = await readProjectTypeState();
161
+ if (!projectType.ready) {
162
+ return {
163
+ adapter: null,
164
+ baseBranch: "main",
165
+ config: null,
166
+ projectConfig: null,
167
+ projectMessage: projectType.message,
168
+ projectReady: false,
169
+ projectType,
170
+ targetRoot: resolvedTargetRoot
171
+ };
172
+ }
173
+
174
+ const adapter = await adapterRegistry.createAdapter(projectType.projectType);
175
+ const config = await readProjectConfigForAdapter(adapter, projectType);
176
+ const projectReady = config.ready === true;
177
+ return {
178
+ adapter,
179
+ baseBranch: "main",
180
+ config,
181
+ projectConfig: config,
182
+ projectMessage: projectReady
183
+ ? ""
184
+ : config.message || "Save Vibe64 project configuration before using project tools.",
185
+ projectReady,
186
+ projectType,
187
+ targetRoot: resolvedTargetRoot
188
+ };
189
+ }
190
+
191
+ async function createProjectToolRegistry(context = {}) {
192
+ const adapterTools = typeof context.adapter?.listProjectTools === "function"
193
+ ? await context.adapter.listProjectTools({
194
+ adapter: context.adapter,
195
+ config: context.config,
196
+ projectConfig: context.projectConfig,
197
+ projectType: context.projectType,
198
+ targetRoot: resolvedTargetRoot
199
+ })
200
+ : [];
201
+ const adapterToolModule = Array.isArray(adapterTools) && adapterTools.length
202
+ ? [{
203
+ id: `adapter.${context.adapter.id}`,
204
+ tools: adapterTools
205
+ }]
206
+ : [];
207
+ return createCoreProjectToolRegistry({
208
+ toolModules: adapterToolModule
209
+ });
210
+ }
211
+
212
+ function projectToolRunParameters(input = {}) {
213
+ const inputObject = input && typeof input === "object" && !Array.isArray(input) ? input : {};
214
+ const parameters = inputObject.parameters || inputObject.input || {};
215
+ return parameters && typeof parameters === "object" && !Array.isArray(parameters)
216
+ ? parameters
217
+ : {};
218
+ }
219
+
220
+ async function listProjectToolState() {
221
+ const context = await projectToolContext();
222
+ const registry = await createProjectToolRegistry(context);
223
+ return registry.listTools(context);
224
+ }
225
+
226
+ async function prepareProjectToolRunState(toolId = "", input = {}) {
227
+ const context = await projectToolContext();
228
+ const registry = await createProjectToolRegistry(context);
229
+ const run = await registry.resolveToolRun(toolId, {
230
+ context,
231
+ parameters: projectToolRunParameters(input)
232
+ });
233
+ if (run.type === "command" && run.spec?.ok === false) {
234
+ const error = new Error(run.spec.message || `${run.tool.label} cannot start.`);
235
+ error.code = "vibe64_project_tool_not_ready";
236
+ throw error;
237
+ }
238
+ if (run.type === "prompt" && !run.prompt) {
239
+ const error = new Error(`${run.tool.label} did not produce a prompt.`);
240
+ error.code = "vibe64_project_tool_not_ready";
241
+ throw error;
242
+ }
243
+ return {
244
+ ...run,
245
+ adapter: context.adapter
246
+ ? {
247
+ id: context.adapter.id,
248
+ label: context.adapter.label
249
+ }
250
+ : null,
251
+ targetRoot: resolvedTargetRoot
252
+ };
253
+ }
254
+
156
255
  async function readProjectConfigForAdapter(adapter, projectType) {
157
256
  const config = await projectConfigStore.readConfig(
158
257
  await projectConfigDefinition(adapter, projectType)
@@ -223,6 +322,8 @@ function createService({
223
322
  }
224
323
 
225
324
  return Object.freeze({
325
+ targetRoot: resolvedTargetRoot,
326
+
226
327
  async createRuntime() {
227
328
  return createRuntime();
228
329
  },
@@ -262,6 +363,24 @@ function createService({
262
363
  return projectConfigStore.environment();
263
364
  },
264
365
 
366
+ async listProjectTools() {
367
+ return projectResult(async () => {
368
+ return {
369
+ ok: true,
370
+ tools: await listProjectToolState()
371
+ };
372
+ });
373
+ },
374
+
375
+ async prepareProjectToolRun(toolId, input = {}) {
376
+ return projectResult(async () => {
377
+ return {
378
+ ok: true,
379
+ ...await prepareProjectToolRunState(toolId, input)
380
+ };
381
+ });
382
+ },
383
+
265
384
  async saveProjectType(input = {}) {
266
385
  return projectResult(async () => {
267
386
  return {
@@ -278,9 +397,7 @@ function createService({
278
397
  ok: true
279
398
  };
280
399
  });
281
- },
282
-
283
- targetRoot: resolvedTargetRoot
400
+ }
284
401
  });
285
402
  }
286
403
 
@@ -0,0 +1,135 @@
1
+ import {
2
+ configTextValue
3
+ } from "@local/vibe64-adapters/server/configValues";
4
+ import {
5
+ VIBE64_DEPLOY_PRODUCTION_COMMAND_CONFIG,
6
+ VIBE64_DEPLOY_STAGING_COMMAND_CONFIG
7
+ } from "@local/vibe64-adapters/server/configStore";
8
+ import {
9
+ projectSyncMainCheckoutTerminalSpec
10
+ } from "@local/vibe64-adapters/server/workflowCommandTerminal/mergeSync";
11
+ import {
12
+ normalizeText
13
+ } from "@local/vibe64-core/server/core";
14
+ import {
15
+ deepFreeze
16
+ } from "@local/vibe64-core/server/deepFreeze";
17
+ import {
18
+ createProjectToolRegistry,
19
+ registerProjectToolContributorModules
20
+ } from "./projectToolRegistry.js";
21
+
22
+ function projectConfigCommand(context = {}, fieldId = "") {
23
+ return configTextValue(context.config || context.projectConfig || {}, fieldId);
24
+ }
25
+
26
+ function projectToolsReady(context = {}) {
27
+ return context.projectReady !== false;
28
+ }
29
+
30
+ function projectToolsDisabledReason(context = {}) {
31
+ return normalizeText(context.projectMessage) || "Save Vibe64 project configuration before using project tools.";
32
+ }
33
+
34
+ function deployCommandDisabledReason(label = "", fieldId = "") {
35
+ return `Configure ${fieldId} before using ${label}.`;
36
+ }
37
+
38
+ function deployCommandTool({
39
+ configFieldId = "",
40
+ description = "",
41
+ id = "",
42
+ label = ""
43
+ } = {}) {
44
+ return {
45
+ id,
46
+ label,
47
+ description,
48
+ type: "command",
49
+ parameters: [],
50
+ requiresConfirmation: true,
51
+ confirmationMessage: `${label} will run the saved deploy command against the main project checkout.`,
52
+ enabled: (context) => projectToolsReady(context) && Boolean(projectConfigCommand(context, configFieldId)),
53
+ disabledReason: (context) => {
54
+ if (!projectToolsReady(context)) {
55
+ return projectToolsDisabledReason(context);
56
+ }
57
+ return projectConfigCommand(context, configFieldId)
58
+ ? ""
59
+ : deployCommandDisabledReason(label, configFieldId);
60
+ },
61
+ async command(context = {}) {
62
+ const command = projectConfigCommand(context, configFieldId);
63
+ return {
64
+ args: [
65
+ "-lc",
66
+ command
67
+ ],
68
+ command: "bash",
69
+ commandPreview: command,
70
+ cwd: context.targetRoot,
71
+ ok: true
72
+ };
73
+ }
74
+ };
75
+ }
76
+
77
+ const coreProjectToolModule = deepFreeze({
78
+ id: "core",
79
+ tools: [
80
+ deployCommandTool({
81
+ configFieldId: VIBE64_DEPLOY_PRODUCTION_COMMAND_CONFIG,
82
+ description: "Run the configured production deployment command from the main project checkout.",
83
+ id: "push_to_production",
84
+ label: "Push to production"
85
+ }),
86
+ deployCommandTool({
87
+ configFieldId: VIBE64_DEPLOY_STAGING_COMMAND_CONFIG,
88
+ description: "Run the configured staging deployment command from the main project checkout.",
89
+ id: "push_to_staging",
90
+ label: "Push to staging"
91
+ }),
92
+ {
93
+ id: "sync_main_with_main",
94
+ label: "Sync main with main",
95
+ description: "Fetch, checkout, and fast-forward the main checkout from origin.",
96
+ type: "command",
97
+ parameters: [],
98
+ enabled: projectToolsReady,
99
+ disabledReason: (context) => projectToolsReady(context) ? "" : projectToolsDisabledReason(context),
100
+ async command(context = {}) {
101
+ return projectSyncMainCheckoutTerminalSpec({
102
+ baseBranch: normalizeText(context.baseBranch) || "main",
103
+ targetRoot: context.targetRoot
104
+ });
105
+ }
106
+ }
107
+ ]
108
+ });
109
+
110
+ const coreProjectToolModules = deepFreeze([
111
+ coreProjectToolModule
112
+ ]);
113
+
114
+ function registerCoreProjectToolModules(registry) {
115
+ return registerProjectToolContributorModules(registry, {
116
+ toolModules: coreProjectToolModules
117
+ });
118
+ }
119
+
120
+ function createCoreProjectToolRegistry({
121
+ toolModules = []
122
+ } = {}) {
123
+ const registry = createProjectToolRegistry();
124
+ registerCoreProjectToolModules(registry);
125
+ return registerProjectToolContributorModules(registry, {
126
+ toolModules
127
+ });
128
+ }
129
+
130
+ export {
131
+ coreProjectToolModule,
132
+ coreProjectToolModules,
133
+ createCoreProjectToolRegistry,
134
+ registerCoreProjectToolModules
135
+ };
@@ -1,14 +1,18 @@
1
1
  export * from "./currentStepInputHelperServer.js";
2
+ export * from "./coreProjectTools.js";
3
+ export * from "./projectToolRegistry.js";
2
4
  export * from "./registerCoreWorkflowModules.js";
3
5
  export * from "./runtime.js";
4
6
  export * from "./sessionDebugLog.js";
5
7
  export * from "./sessionDebugLogCore.js";
6
8
  export * from "./sessionStore.js";
9
+ export * from "./sessionWorktreeState.js";
7
10
  export * from "./setupReadiness.js";
8
11
  export * from "./terminalFailureFixRequest.js";
9
12
  export * from "./workflow.js";
10
13
  export * from "./workflowArtifacts.js";
11
14
  export * from "./workflowConditions.js";
15
+ export * from "./workflowDefinitionComposers.js";
12
16
  export * from "./workflowDefinitionBuilders.js";
13
17
  export * from "./workflowMachine.js";
14
18
  export * from "./workflowPresentation.js";