@fieldwangai/agentflow 0.1.32 → 0.1.33

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.
@@ -41,12 +41,15 @@ import { getRunDir, sanitizeAgentflowUserId } from "../lib/paths.mjs";
41
41
  import {
42
42
  buildSkillsContext,
43
43
  buildSkillsContextFromRegistry,
44
+ buildDefaultWorkspaceContext,
44
45
  expandRuntimePlaceholders,
45
46
  normalizeSkillsContext,
46
47
  normalizeWorkspaceContext,
47
48
  parseSkillKeyList,
48
49
  resolveWorkspaceTarget,
49
50
  } from "../lib/runtime-context.mjs";
51
+ import { buildGitContext, loadGitWorktree, normalizeGitContext, unloadGitWorktree } from "../lib/git-worktree.mjs";
52
+ import { createGitLabMergeRequest } from "../lib/gitlab-mr.mjs";
50
53
 
51
54
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
52
55
 
@@ -264,6 +267,12 @@ function isTruthyInput(value) {
264
267
  return text === "true" || text === "1" || text === "yes" || text === "y" || text === "on";
265
268
  }
266
269
 
270
+ function resolveMaybeWorkspacePath(raw, workspaceContext, extra = {}) {
271
+ const text = String(raw || "").trim();
272
+ if (!text) return "";
273
+ return resolveWorkspaceTarget(text, workspaceContext, extra);
274
+ }
275
+
267
276
  function emitGitCheckoutNode(workspaceRoot, flowName, uuid, instanceId, execId, resultPathRel) {
268
277
  const runDir = getRunDir(workspaceRoot, flowName, uuid);
269
278
  const { inputs, workspaceContext } = resolveNodeRuntimeContexts(workspaceRoot, flowName, uuid, instanceId);
@@ -312,6 +321,12 @@ function emitGitCheckoutNode(workspaceRoot, flowName, uuid, instanceId, execId,
312
321
 
313
322
  const currentBranch = runGit(["rev-parse", "--abbrev-ref", "HEAD"], targetDir).stdout.trim();
314
323
  const commit = runGit(["rev-parse", "HEAD"], targetDir).stdout.trim();
324
+ const gitContext = buildGitContext({
325
+ repoPath: targetDir,
326
+ branch: currentBranch === "HEAD" ? "DETACHED" : currentBranch,
327
+ commit,
328
+ remote: String(inputs.remote || "origin").trim() || "origin",
329
+ });
315
330
  const outWorkspaceContext = {
316
331
  version: 1,
317
332
  label: inputs.label || sanitizeRepoDirName(repoUrl),
@@ -326,10 +341,127 @@ function emitGitCheckoutNode(workspaceRoot, flowName, uuid, instanceId, execId,
326
341
  writeOutputSlot(runDir, instanceId, execId, "commit", commit);
327
342
  writeOutputSlot(runDir, instanceId, execId, "changed", changed ? "true" : "false");
328
343
  writeOutputSlot(runDir, instanceId, execId, "workspaceContext", JSON.stringify(outWorkspaceContext));
344
+ writeOutputSlot(runDir, instanceId, execId, "gitContext", JSON.stringify(gitContext));
329
345
  writeResult(workspaceRoot, flowName, uuid, instanceId, { status: "success", message: `git ${action}: ${currentBranch}@${commit.slice(0, 8)}` }, { execId });
330
346
  return emitLocalNoopPrompt(workspaceRoot, runDir, instanceId, "git-checkout", `Git checkout completed: ${targetDir}\n`);
331
347
  }
332
348
 
349
+ function requireWorkspaceContextInput(inputs, definitionId) {
350
+ if (!String(inputs?.workspaceContext || "").trim()) {
351
+ throw new Error(`${definitionId}: workspaceContext is required`);
352
+ }
353
+ }
354
+
355
+ function emitGitWorktreeLoadNode(workspaceRoot, flowName, uuid, instanceId, execId) {
356
+ const runDir = getRunDir(workspaceRoot, flowName, uuid);
357
+ const { inputs, workspaceContext } = resolveNodeRuntimeContexts(workspaceRoot, flowName, uuid, instanceId);
358
+ requireWorkspaceContextInput(inputs, "tool_git_worktree_load");
359
+ const gitContext = normalizeGitContext(inputs.gitContext);
360
+ const repoPath = resolveMaybeWorkspacePath(inputs.repoPath, workspaceContext) ||
361
+ (gitContext?.repoPath ? path.resolve(gitContext.repoPath) : "");
362
+ if (!repoPath) throw new Error("tool_git_worktree_load: repoPath or gitContext.repoPath is required");
363
+ const branch = String(inputs.branch || "").trim();
364
+ const worktreePath = resolveMaybeWorkspacePath(inputs.worktreePath, workspaceContext, { branch }) ||
365
+ (gitContext?.worktreePath ? path.resolve(gitContext.worktreePath) : "");
366
+ const result = loadGitWorktree({
367
+ repoPath,
368
+ branch,
369
+ worktreePath,
370
+ pipelineWorkspace: workspaceContext.pipelineWorkspace || path.resolve(workspaceRoot),
371
+ });
372
+ const outWorkspaceContext = {
373
+ version: 1,
374
+ label: result.branch === "DETACHED" ? `worktree:${result.commit.slice(0, 8)}` : `worktree:${result.branch}`,
375
+ cwd: result.worktreePath,
376
+ workspaceRoot: result.worktreePath,
377
+ pipelineWorkspace: workspaceContext.pipelineWorkspace || path.resolve(workspaceRoot),
378
+ flowDir: workspaceContext.flowDir,
379
+ previous: workspaceContext,
380
+ };
381
+ const outGitContext = buildGitContext({
382
+ repoPath: result.repoRoot,
383
+ worktreePath: result.worktreePath,
384
+ branch: result.branch,
385
+ commit: result.commit,
386
+ remote: gitContext?.remote || "origin",
387
+ remoteUrl: gitContext?.remoteUrl || "",
388
+ });
389
+ writeOutputSlot(runDir, instanceId, execId, "worktreePath", result.worktreePath);
390
+ writeOutputSlot(runDir, instanceId, execId, "branch", result.branch);
391
+ writeOutputSlot(runDir, instanceId, execId, "commit", result.commit);
392
+ writeOutputSlot(runDir, instanceId, execId, "workspaceContext", JSON.stringify(outWorkspaceContext));
393
+ writeOutputSlot(runDir, instanceId, execId, "gitContext", JSON.stringify(outGitContext));
394
+ writeResult(workspaceRoot, flowName, uuid, instanceId, {
395
+ status: "success",
396
+ message: `worktree loaded: ${result.worktreePath} (${result.branch}@${result.commit.slice(0, 8)})`,
397
+ }, { execId });
398
+ return emitLocalNoopPrompt(workspaceRoot, runDir, instanceId, "git-worktree-load", `Git worktree loaded: ${result.worktreePath}\n`);
399
+ }
400
+
401
+ function emitGitWorktreeUnloadNode(workspaceRoot, flowName, uuid, instanceId, execId) {
402
+ const runDir = getRunDir(workspaceRoot, flowName, uuid);
403
+ const { inputs, workspaceContext, flowJson } = resolveNodeRuntimeContexts(workspaceRoot, flowName, uuid, instanceId);
404
+ requireWorkspaceContextInput(inputs, "tool_git_worktree_unload");
405
+ const gitContext = normalizeGitContext(inputs.gitContext);
406
+ const repoPath = resolveMaybeWorkspacePath(inputs.repoPath, workspaceContext) ||
407
+ (gitContext?.repoPath ? path.resolve(gitContext.repoPath) : "");
408
+ const worktreePath = resolveMaybeWorkspacePath(inputs.worktreePath, workspaceContext) ||
409
+ (gitContext?.worktreePath ? path.resolve(gitContext.worktreePath) : "");
410
+ if (!repoPath) throw new Error("tool_git_worktree_unload: repoPath or gitContext.repoPath is required");
411
+ if (!worktreePath) throw new Error("tool_git_worktree_unload: worktreePath or gitContext.worktreePath is required");
412
+ const force = isTruthyInput(inputs.force);
413
+ const prune = String(inputs.prune ?? "true").trim().toLowerCase() !== "false";
414
+ const result = unloadGitWorktree({ repoPath, worktreePath, force, prune });
415
+ const nextWorkspaceContext = workspaceContext.previous
416
+ ? normalizeWorkspaceContext(workspaceContext.previous, workspaceRoot, flowName, flowJson)
417
+ : buildDefaultWorkspaceContext(workspaceRoot, flowName, flowJson);
418
+ writeOutputSlot(runDir, instanceId, execId, "removed", "true");
419
+ writeOutputSlot(runDir, instanceId, execId, "message", result.message);
420
+ writeOutputSlot(runDir, instanceId, execId, "workspaceContext", JSON.stringify(nextWorkspaceContext));
421
+ writeResult(workspaceRoot, flowName, uuid, instanceId, {
422
+ status: "success",
423
+ message: result.message,
424
+ }, { execId });
425
+ return emitLocalNoopPrompt(workspaceRoot, runDir, instanceId, "git-worktree-unload", `${result.message}\n`);
426
+ }
427
+
428
+ async function emitGitLabCreateMrNode(workspaceRoot, flowName, uuid, instanceId, execId) {
429
+ const runDir = getRunDir(workspaceRoot, flowName, uuid);
430
+ const { inputs, workspaceContext } = resolveNodeRuntimeContexts(workspaceRoot, flowName, uuid, instanceId);
431
+ const repoPath = resolveMaybeWorkspacePath(inputs.repoPath, workspaceContext);
432
+ const result = await createGitLabMergeRequest({
433
+ gitContext: inputs.gitContext,
434
+ workspaceCwd: workspaceContext.cwd,
435
+ repoPath,
436
+ sourceBranch: inputs.sourceBranch,
437
+ targetBranch: inputs.targetBranch,
438
+ title: inputs.title,
439
+ description: inputs.description,
440
+ draft: inputs.draft,
441
+ labels: inputs.labels,
442
+ push: inputs.push,
443
+ remote: inputs.remote,
444
+ tokenEnv: inputs.tokenEnv,
445
+ gitlabApiBase: inputs.gitlabApiBase,
446
+ removeSourceBranch: inputs.removeSourceBranch,
447
+ squash: inputs.squash,
448
+ }, process.env);
449
+ writeOutputSlot(runDir, instanceId, execId, "mrUrl", result.mrUrl);
450
+ writeOutputSlot(runDir, instanceId, execId, "created", result.created ? "true" : "false");
451
+ writeOutputSlot(runDir, instanceId, execId, "mrIid", result.mrIid ?? "");
452
+ writeOutputSlot(runDir, instanceId, execId, "projectId", result.projectId ?? "");
453
+ writeOutputSlot(runDir, instanceId, execId, "sourceBranch", result.sourceBranch ?? "");
454
+ writeOutputSlot(runDir, instanceId, execId, "targetBranch", result.targetBranch ?? "");
455
+ writeOutputSlot(runDir, instanceId, execId, "title", result.title ?? "");
456
+ writeOutputSlot(runDir, instanceId, execId, "message", result.message ?? "");
457
+ writeResult(workspaceRoot, flowName, uuid, instanceId, {
458
+ status: "success",
459
+ message: result.message || result.mrUrl,
460
+ body: result.mrUrl,
461
+ }, { execId });
462
+ return emitLocalNoopPrompt(workspaceRoot, runDir, instanceId, "gitlab-create-mr", `${result.message || "GitLab MR ready"}\n${result.mrUrl}\n`);
463
+ }
464
+
333
465
  function emitCdWorkspaceNode(workspaceRoot, flowName, uuid, instanceId, execId) {
334
466
  const runDir = getRunDir(workspaceRoot, flowName, uuid);
335
467
  const { inputs, workspaceContext } = resolveNodeRuntimeContexts(workspaceRoot, flowName, uuid, instanceId);
@@ -461,7 +593,7 @@ function emitToolPrintNode(workspaceRoot, flowName, uuid, instanceId, execId) {
461
593
  const flowJson = readFlowJsonObject(workspaceRoot, flowName, uuid);
462
594
  const data = getResolvedValues(workspaceRoot, flowName, uuid, instanceId);
463
595
  const inputs = data.ok ? (data.resolvedInputs || {}) : {};
464
- const skipNames = new Set(["prev", "next", "workspaceContext", "skillsContext", "workspaceRoot", "pipelineWorkspace", "flowName", "runDir", "flowDir", "cwd"]);
596
+ const skipNames = new Set(["prev", "next", "workspaceContext", "gitContext", "skillsContext", "workspaceRoot", "pipelineWorkspace", "flowName", "runDir", "flowDir", "cwd"]);
465
597
 
466
598
  let content = readPrintableValue(inputs.content, runDir);
467
599
  if (!content) {
@@ -681,7 +813,7 @@ ${directCommand}
681
813
  return { optionalPromptPath: relativePath.replace(/\\/g, "/"), directCommand };
682
814
  }
683
815
 
684
- function main() {
816
+ async function main() {
685
817
  const args = process.argv.slice(2);
686
818
  if (args.length < 4) {
687
819
  console.error(
@@ -1001,18 +1133,24 @@ function main() {
1001
1133
  return;
1002
1134
  }
1003
1135
 
1004
- if (definitionId === "tool_git_checkout" || definitionId === "control_cd_workspace" || definitionId === "control_user_workspace" || definitionId === "control_load_skills" || definitionId === "tool_print") {
1136
+ if (definitionId === "tool_git_checkout" || definitionId === "tool_git_worktree_load" || definitionId === "tool_git_worktree_unload" || definitionId === "tool_gitlab_create_mr" || definitionId === "control_cd_workspace" || definitionId === "control_user_workspace" || definitionId === "control_load_skills" || definitionId === "tool_print") {
1005
1137
  try {
1006
1138
  const promptPath =
1007
1139
  definitionId === "tool_git_checkout"
1008
1140
  ? emitGitCheckoutNode(workspaceRoot, flowName, uuid, instanceId, execId, resultPathRel)
1009
- : definitionId === "control_cd_workspace"
1010
- ? emitCdWorkspaceNode(workspaceRoot, flowName, uuid, instanceId, execId)
1011
- : definitionId === "control_user_workspace"
1012
- ? emitUserWorkspaceNode(workspaceRoot, flowName, uuid, instanceId, execId)
1013
- : definitionId === "control_load_skills"
1014
- ? emitLoadSkillsNode(workspaceRoot, flowName, uuid, instanceId, execId)
1015
- : emitToolPrintNode(workspaceRoot, flowName, uuid, instanceId, execId);
1141
+ : definitionId === "tool_git_worktree_load"
1142
+ ? emitGitWorktreeLoadNode(workspaceRoot, flowName, uuid, instanceId, execId)
1143
+ : definitionId === "tool_git_worktree_unload"
1144
+ ? emitGitWorktreeUnloadNode(workspaceRoot, flowName, uuid, instanceId, execId)
1145
+ : definitionId === "tool_gitlab_create_mr"
1146
+ ? await emitGitLabCreateMrNode(workspaceRoot, flowName, uuid, instanceId, execId)
1147
+ : definitionId === "control_cd_workspace"
1148
+ ? emitCdWorkspaceNode(workspaceRoot, flowName, uuid, instanceId, execId)
1149
+ : definitionId === "control_user_workspace"
1150
+ ? emitUserWorkspaceNode(workspaceRoot, flowName, uuid, instanceId, execId)
1151
+ : definitionId === "control_load_skills"
1152
+ ? emitLoadSkillsNode(workspaceRoot, flowName, uuid, instanceId, execId)
1153
+ : emitToolPrintNode(workspaceRoot, flowName, uuid, instanceId, execId);
1016
1154
  writeCacheJsonForNode(workspaceRoot, flowName, uuid, instanceId, execId);
1017
1155
  logToRunTag(workspaceRoot, flowName, uuid, "pre-process", { event: "runtime-context-node", instanceId, definitionId });
1018
1156
  console.log(JSON.stringify({
@@ -1103,4 +1241,7 @@ function main() {
1103
1241
  console.log(JSON.stringify(output));
1104
1242
  }
1105
1243
 
1106
- main();
1244
+ main().catch((e) => {
1245
+ console.error(JSON.stringify({ ok: false, error: e.message || String(e) }));
1246
+ process.exit(1);
1247
+ });
@@ -493,26 +493,16 @@ function checkFlowCore(nodes, edges, flowDir, nodeIdToSlots, getNodeBody, instan
493
493
  }
494
494
  }
495
495
 
496
- // provide_str / provide_file output 类型校验
497
- if (defId === "provide_str") {
496
+ // provide_str / provide_file / provide_bool output 类型校验
497
+ if (defId === "provide_str" || defId === "provide_file" || defId === "provide_bool") {
498
498
  const out = Array.isArray(inst.output) ? inst.output : [];
499
+ const expectedType = defId === "provide_file" ? "file" : defId === "provide_bool" ? "bool" : "text";
499
500
  if (out.length !== 1) {
500
- errors.push(`节点 "${n.id}"(provide_str)output 必须仅有 1 个槽位(value:text),当前 ${out.length} 个`);
501
+ errors.push(`节点 "${n.id}"(${defId})output 必须仅有 1 个槽位(value:${expectedType}),当前 ${out.length} 个`);
501
502
  } else {
502
503
  const t0 = normType(out[0] && out[0].type);
503
- if (t0 !== "text") {
504
- errors.push(`节点 "${n.id}"(provide_str)output[0].type 必须为 \`text\`,当前为 \`${t0 || "(空)"}\``);
505
- }
506
- }
507
- }
508
- if (defId === "provide_file") {
509
- const out = Array.isArray(inst.output) ? inst.output : [];
510
- if (out.length !== 1) {
511
- errors.push(`节点 "${n.id}"(provide_file)output 必须仅有 1 个槽位(value:file),当前 ${out.length} 个`);
512
- } else {
513
- const t0 = normType(out[0] && out[0].type);
514
- if (t0 !== "file") {
515
- errors.push(`节点 "${n.id}"(provide_file)output[0].type 必须为 \`file\`,当前为 \`${t0 || "(空)"}\``);
504
+ if (t0 !== expectedType) {
505
+ errors.push(`节点 "${n.id}"(${defId})output[0].type 必须为 \`${expectedType}\`,当前为 \`${t0 || "(空)"}\``);
516
506
  }
517
507
  }
518
508
  }
@@ -675,7 +665,7 @@ function computeValidation(loaded, workspaceRoot) {
675
665
  if (!isNodeEdge) continue;
676
666
  if (srcDef.startsWith("provide_") || tgtDef.startsWith("provide_")) {
677
667
  validationErrors.push(
678
- `provide_* 节点不得出现在控制链上(node→node 边):${e.source} ${sh} -> ${e.target} ${th};provide 仅作数据源,请改连下游 text/file 数据槽`
668
+ `provide_* 节点不得出现在控制链上(node→node 边):${e.source} ${sh} -> ${e.target} ${th};provide 仅作数据源,请改连下游 text/file/bool 数据槽`
679
669
  );
680
670
  }
681
671
  }
@@ -0,0 +1,31 @@
1
+ ---
2
+ # Built-in node: HTML Display
3
+ description: Display HTML content in workspace canvas; passes HTML downstream as text
4
+ displayName: HTML Display
5
+ input:
6
+ - type: node
7
+ name: prev
8
+ default: ""
9
+ - type: text
10
+ name: content
11
+ default: ""
12
+ required: true
13
+ showOnNode: true
14
+ - type: file
15
+ name: filePath
16
+ default: ""
17
+ showOnNode: false
18
+ - type: text
19
+ name: workspaceContext
20
+ default: ""
21
+ showOnNode: false
22
+ output:
23
+ - type: text
24
+ name: content
25
+ default: ""
26
+ showOnNode: false
27
+ - type: node
28
+ name: next
29
+ default: ""
30
+ ---
31
+ ${content}
@@ -0,0 +1,35 @@
1
+ ---
2
+ # Built-in node: Image Display
3
+ description: Display an image URL, data URL, or image path in workspace canvas; passes source downstream as text
4
+ displayName: Image Display
5
+ input:
6
+ - type: node
7
+ name: prev
8
+ default: ""
9
+ - type: text
10
+ name: src
11
+ default: ""
12
+ required: true
13
+ showOnNode: true
14
+ - type: file
15
+ name: filePath
16
+ default: ""
17
+ showOnNode: false
18
+ - type: text
19
+ name: alt
20
+ default: ""
21
+ showOnNode: false
22
+ - type: text
23
+ name: workspaceContext
24
+ default: ""
25
+ showOnNode: false
26
+ output:
27
+ - type: text
28
+ name: src
29
+ default: ""
30
+ showOnNode: false
31
+ - type: node
32
+ name: next
33
+ default: ""
34
+ ---
35
+ ${src}
@@ -0,0 +1,11 @@
1
+ ---
2
+ # 内置节点:直接提供布尔值
3
+ description: Provide a boolean value directly, value will be passed to downstream as true or false
4
+ displayName: Boolean
5
+ input: []
6
+ output:
7
+ - type: bool
8
+ name: value
9
+ default: "false"
10
+ ---
11
+ ${USER_PROMPT}
@@ -8,6 +8,7 @@ description: |
8
8
  - If `targetDir` is empty, the repository is cloned into `${pipelineWorkspace}/.workspace/agentflow/git-repos/<repo-name>`.
9
9
  - Set `includeSubmodules` to `true` to clone/update Git submodules recursively.
10
10
  - The `workspaceContext` output can be connected to CD Workspace, Load Skills, agent, or tool nodes.
11
+ - The `gitContext` output can be connected to Worktree, GitLab MR, or other Git nodes.
11
12
  displayName: Git Checkout
12
13
  input:
13
14
  - type: node
@@ -31,6 +32,9 @@ input:
31
32
  - type: bool
32
33
  name: includeSubmodules
33
34
  default: "false"
35
+ - type: text
36
+ name: remote
37
+ default: "origin"
34
38
  - type: text
35
39
  name: workspaceContext
36
40
  default: ""
@@ -53,5 +57,8 @@ output:
53
57
  - type: text
54
58
  name: workspaceContext
55
59
  default: ""
60
+ - type: text
61
+ name: gitContext
62
+ default: ""
56
63
  ---
57
- Clone or update `${repoUrl}` and output a workspace context for the checked-out repository.
64
+ Clone or update `${repoUrl}` and output workspace/git contexts for the checked-out repository.
@@ -0,0 +1,54 @@
1
+ ---
2
+ # Built-in node: Git Worktree Load
3
+ description: |
4
+ Create or reuse a Git worktree and expose it as the downstream workspace context.
5
+
6
+ - `repoPath` is required unless `gitContext.repoPath` is connected.
7
+ - `workspaceContext` is required so the node can preserve the previous execution context.
8
+ - `branch` is optional. When empty, AgentFlow creates a detached worktree at the current HEAD.
9
+ - `worktreePath` is optional. When empty, AgentFlow creates a path under `${pipelineWorkspace}/.workspace/agentflow/worktrees`.
10
+ - Existing worktree paths are reused only when they are registered by `git worktree list` for the given repo.
11
+ displayName: Load Worktree
12
+ input:
13
+ - type: node
14
+ name: prev
15
+ default: ""
16
+ - type: file
17
+ name: repoPath
18
+ default: ""
19
+ showOnNode: true
20
+ - type: text
21
+ name: branch
22
+ default: ""
23
+ showOnNode: true
24
+ - type: file
25
+ name: worktreePath
26
+ default: ""
27
+ - type: text
28
+ name: gitContext
29
+ default: ""
30
+ - type: text
31
+ name: workspaceContext
32
+ default: ""
33
+ required: true
34
+ output:
35
+ - type: node
36
+ name: next
37
+ default: ""
38
+ - type: file
39
+ name: worktreePath
40
+ default: ""
41
+ - type: text
42
+ name: branch
43
+ default: ""
44
+ - type: text
45
+ name: commit
46
+ default: ""
47
+ - type: text
48
+ name: workspaceContext
49
+ default: ""
50
+ - type: text
51
+ name: gitContext
52
+ default: ""
53
+ ---
54
+ Load a Git worktree from `${repoPath}` and switch downstream workspace context to it.
@@ -0,0 +1,51 @@
1
+ ---
2
+ # Built-in node: Git Worktree Unload
3
+ description: |
4
+ Remove a Git worktree.
5
+
6
+ - `repoPath` is required unless `gitContext.repoPath` is connected.
7
+ - `worktreePath` is required unless `gitContext.worktreePath` is connected.
8
+ - `workspaceContext` is required so the node can restore the previous execution context.
9
+ - By default `force` is false; dirty worktrees fail instead of being removed.
10
+ - By default `prune` is true.
11
+ displayName: Unload Worktree
12
+ input:
13
+ - type: node
14
+ name: prev
15
+ default: ""
16
+ - type: file
17
+ name: repoPath
18
+ default: ""
19
+ showOnNode: true
20
+ - type: file
21
+ name: worktreePath
22
+ default: ""
23
+ showOnNode: true
24
+ - type: text
25
+ name: gitContext
26
+ default: ""
27
+ - type: text
28
+ name: workspaceContext
29
+ default: ""
30
+ required: true
31
+ - type: bool
32
+ name: force
33
+ default: "false"
34
+ - type: bool
35
+ name: prune
36
+ default: "true"
37
+ output:
38
+ - type: node
39
+ name: next
40
+ default: ""
41
+ - type: bool
42
+ name: removed
43
+ default: ""
44
+ - type: text
45
+ name: workspaceContext
46
+ default: ""
47
+ - type: text
48
+ name: message
49
+ default: ""
50
+ ---
51
+ Remove Git worktree `${worktreePath}` from repository `${repoPath}`.
@@ -0,0 +1,113 @@
1
+ ---
2
+ # Built-in node: GitLab Create MR
3
+ description: |
4
+ Create or reuse a GitLab merge request for the current branch.
5
+
6
+ - `gitContext` and `workspaceContext` can be connected from Git Checkout / Load Worktree.
7
+ - `repoPath` is optional. When empty, AgentFlow uses `gitContext.worktreePath`, `gitContext.repoPath`, or `workspaceContext.cwd`.
8
+ - `sourceBranch`, `targetBranch`, `title`, `description`, `draft`, and `labels` are optional. When empty, AgentFlow derives sensible defaults from git.
9
+ - `tokenEnv` is optional. Defaults to `GITLAB_TOKEN,GITLAB_PRIVATE_TOKEN`.
10
+ - `gitlabApiBase` is optional. When empty, AgentFlow uses `https://${gitContext.host}/api/v4`.
11
+ displayName: Create GitLab MR
12
+ input:
13
+ - type: node
14
+ name: prev
15
+ default: ""
16
+ - type: file
17
+ name: repoPath
18
+ default: ""
19
+ showOnNode: false
20
+ - type: text
21
+ name: gitContext
22
+ default: ""
23
+ showOnNode: true
24
+ - type: text
25
+ name: workspaceContext
26
+ default: ""
27
+ showOnNode: false
28
+ - type: text
29
+ name: sourceBranch
30
+ default: ""
31
+ showOnNode: false
32
+ - type: text
33
+ name: targetBranch
34
+ default: ""
35
+ showOnNode: false
36
+ - type: text
37
+ name: title
38
+ default: ""
39
+ showOnNode: false
40
+ - type: text
41
+ name: description
42
+ default: ""
43
+ showOnNode: false
44
+ - type: bool
45
+ name: draft
46
+ default: "false"
47
+ showOnNode: false
48
+ - type: text
49
+ name: labels
50
+ default: ""
51
+ showOnNode: false
52
+ - type: bool
53
+ name: push
54
+ default: "true"
55
+ showOnNode: false
56
+ - type: text
57
+ name: remote
58
+ default: "origin"
59
+ showOnNode: false
60
+ - type: text
61
+ name: tokenEnv
62
+ default: ""
63
+ showOnNode: false
64
+ - type: text
65
+ name: gitlabApiBase
66
+ default: ""
67
+ showOnNode: false
68
+ - type: bool
69
+ name: removeSourceBranch
70
+ default: "false"
71
+ showOnNode: false
72
+ - type: bool
73
+ name: squash
74
+ default: "false"
75
+ showOnNode: false
76
+ output:
77
+ - type: node
78
+ name: next
79
+ default: ""
80
+ - type: text
81
+ name: mrUrl
82
+ default: ""
83
+ required: true
84
+ - type: bool
85
+ name: created
86
+ default: ""
87
+ showOnNode: false
88
+ - type: text
89
+ name: mrIid
90
+ default: ""
91
+ showOnNode: false
92
+ - type: text
93
+ name: projectId
94
+ default: ""
95
+ showOnNode: false
96
+ - type: text
97
+ name: sourceBranch
98
+ default: ""
99
+ showOnNode: false
100
+ - type: text
101
+ name: targetBranch
102
+ default: ""
103
+ showOnNode: false
104
+ - type: text
105
+ name: title
106
+ default: ""
107
+ showOnNode: false
108
+ - type: text
109
+ name: message
110
+ default: ""
111
+ showOnNode: false
112
+ ---
113
+ Create or reuse a GitLab merge request and output `${mrUrl}`.